mirror of https://github.com/GNOME/gimp.git
Support for custom plug-in interpreters, independent of OS support.
2005-02-20 Manish Singh <yosh@gimp.org> Support for custom plug-in interpreters, independent of OS support. * app/core/Makefile.am * app/core/core-types.h * app/core/gimpinterpreterdb.[ch]: implemented GimpInterpreterDB, which handles registering and resolving custom plug-in interpreters. * app/core/gimp.[ch]: keep a GimpInterpreterDB around. * app/config/gimpcoreconfig.[ch] * app/config/gimprc-blurbs.h * app/dialogs/preferences-dialog.c * app/dialogs/user-install-dialog.c * app/widgets/gimphelp-ids.h: interpreter-path config stuff. * app/plug-in/plug-in.c: use registered interpreters when running plug-ins. * themes/Default/images/preferences/Makefile.am * themes/Default/images/preferences/folders-interp.png: just copied folders-plug-ins.png here, need a better one. * data/interpreters/Makefile.am: creates system interpreter directory. * data/interpreters/default.interp: sample interpreter file info. * data/Makefile.am * configure.in: add data/interpreters directory. * plug-ins/pygimp/Makefile.am: install pygimp.interp, which configures the python interpreter to point to the python we were built with. Also register the .py extension. * etc/gimprc * docs/gimprc.5.in: regenerated
This commit is contained in:
parent
fd809bfe92
commit
9706fce0a3
38
ChangeLog
38
ChangeLog
|
@ -1,3 +1,41 @@
|
|||
2005-02-20 Manish Singh <yosh@gimp.org>
|
||||
|
||||
Support for custom plug-in interpreters, independent of OS support.
|
||||
|
||||
* app/core/Makefile.am
|
||||
* app/core/core-types.h
|
||||
* app/core/gimpinterpreterdb.[ch]: implemented GimpInterpreterDB,
|
||||
which handles registering and resolving custom plug-in interpreters.
|
||||
|
||||
* app/core/gimp.[ch]: keep a GimpInterpreterDB around.
|
||||
|
||||
* app/config/gimpcoreconfig.[ch]
|
||||
* app/config/gimprc-blurbs.h
|
||||
* app/dialogs/preferences-dialog.c
|
||||
* app/dialogs/user-install-dialog.c
|
||||
* app/widgets/gimphelp-ids.h: interpreter-path config stuff.
|
||||
|
||||
* app/plug-in/plug-in.c: use registered interpreters when running
|
||||
plug-ins.
|
||||
|
||||
* themes/Default/images/preferences/Makefile.am
|
||||
* themes/Default/images/preferences/folders-interp.png: just copied
|
||||
folders-plug-ins.png here, need a better one.
|
||||
|
||||
* data/interpreters/Makefile.am: creates system interpreter directory.
|
||||
|
||||
* data/interpreters/default.interp: sample interpreter file info.
|
||||
|
||||
* data/Makefile.am
|
||||
* configure.in: add data/interpreters directory.
|
||||
|
||||
* plug-ins/pygimp/Makefile.am: install pygimp.interp, which configures
|
||||
the python interpreter to point to the python we were built with. Also
|
||||
register the .py extension.
|
||||
|
||||
* etc/gimprc
|
||||
* docs/gimprc.5.in: regenerated
|
||||
|
||||
2005-02-20 Jay Cox <jaycox@gimp.org>
|
||||
|
||||
* plug-ins/common/psd.c: Fix layer mask support. Addresses bug
|
||||
|
|
|
@ -73,6 +73,7 @@ enum
|
|||
PROP_INTERPOLATION_TYPE,
|
||||
PROP_PLUG_IN_PATH,
|
||||
PROP_MODULE_PATH,
|
||||
PROP_INTERPRETER_PATH,
|
||||
PROP_ENVIRON_PATH,
|
||||
PROP_BRUSH_PATH,
|
||||
PROP_BRUSH_PATH_WRITABLE,
|
||||
|
@ -169,6 +170,11 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass)
|
|||
GIMP_CONFIG_PATH_DIR_LIST,
|
||||
gimp_config_build_plug_in_path ("modules"),
|
||||
GIMP_CONFIG_PARAM_RESTART);
|
||||
GIMP_CONFIG_INSTALL_PROP_PATH (object_class, PROP_INTERPRETER_PATH,
|
||||
"interpreter-path", INTERPRETER_PATH_BLURB,
|
||||
GIMP_CONFIG_PATH_DIR_LIST,
|
||||
gimp_config_build_plug_in_path ("interpreters"),
|
||||
GIMP_CONFIG_PARAM_RESTART);
|
||||
GIMP_CONFIG_INSTALL_PROP_PATH (object_class, PROP_ENVIRON_PATH,
|
||||
"environ-path", ENVIRON_PATH_BLURB,
|
||||
GIMP_CONFIG_PATH_DIR_LIST,
|
||||
|
@ -357,6 +363,7 @@ gimp_core_config_finalize (GObject *object)
|
|||
|
||||
g_free (core_config->plug_in_path);
|
||||
g_free (core_config->module_path);
|
||||
g_free (core_config->interpreter_path);
|
||||
g_free (core_config->environ_path);
|
||||
g_free (core_config->brush_path);
|
||||
g_free (core_config->brush_path_writable);
|
||||
|
@ -408,6 +415,10 @@ gimp_core_config_set_property (GObject *object,
|
|||
g_free (core_config->module_path);
|
||||
core_config->module_path = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_INTERPRETER_PATH:
|
||||
g_free (core_config->interpreter_path);
|
||||
core_config->interpreter_path = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_ENVIRON_PATH:
|
||||
g_free (core_config->environ_path);
|
||||
core_config->environ_path = g_value_dup_string (value);
|
||||
|
@ -559,6 +570,9 @@ gimp_core_config_get_property (GObject *object,
|
|||
case PROP_MODULE_PATH:
|
||||
g_value_set_string (value, core_config->module_path);
|
||||
break;
|
||||
case PROP_INTERPRETER_PATH:
|
||||
g_value_set_string (value, core_config->interpreter_path);
|
||||
break;
|
||||
case PROP_ENVIRON_PATH:
|
||||
g_value_set_string (value, core_config->environ_path);
|
||||
break;
|
||||
|
|
|
@ -43,6 +43,7 @@ struct _GimpCoreConfig
|
|||
GimpInterpolationType interpolation_type;
|
||||
gchar *plug_in_path;
|
||||
gchar *module_path;
|
||||
gchar *interpreter_path;
|
||||
gchar *environ_path;
|
||||
gchar *brush_path;
|
||||
gchar *brush_path_writable;
|
||||
|
|
|
@ -173,6 +173,9 @@ N_("Install a private colormap; might be useful on 8-bit (256 colors) displays."
|
|||
N_("Sets the level of interpolation used for scaling and other " \
|
||||
"transformations.")
|
||||
|
||||
#define INTERPRETER_PATH_BLURB \
|
||||
"Sets the interpreter search path."
|
||||
|
||||
#define LAST_OPENED_SIZE_BLURB \
|
||||
N_("How many recently opened image filenames to keep on the File menu.")
|
||||
|
||||
|
|
|
@ -158,6 +158,8 @@ libappcore_a_sources = \
|
|||
gimpimagefile.h \
|
||||
gimpimagemap.c \
|
||||
gimpimagemap.h \
|
||||
gimpinterpreterdb.c \
|
||||
gimpinterpreterdb.h \
|
||||
gimpitem.c \
|
||||
gimpitem.h \
|
||||
gimpitem-linked.c \
|
||||
|
|
|
@ -113,6 +113,7 @@ typedef struct _GimpEnvironTable GimpEnvironTable;
|
|||
/* typedef struct _GimpGrid GimpGrid; in config-types.h */
|
||||
typedef struct _GimpImagefile GimpImagefile;
|
||||
typedef struct _GimpImageMap GimpImageMap;
|
||||
typedef struct _GimpInterpreterDB GimpInterpreterDB;
|
||||
typedef struct _GimpParasiteList GimpParasiteList;
|
||||
typedef struct _GimpPdbProgress GimpPdbProgress;
|
||||
typedef struct _GimpProjection GimpProjection;
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "gimpgradient-load.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpimagefile.h"
|
||||
#include "gimpinterpreterdb.h"
|
||||
#include "gimplist.h"
|
||||
#include "gimpmarshal.h"
|
||||
#include "gimppalette.h"
|
||||
|
@ -230,6 +231,7 @@ gimp_init (Gimp *gimp)
|
|||
|
||||
gimp_modules_init (gimp);
|
||||
|
||||
gimp->interpreter_db = gimp_interpreter_db_new ();
|
||||
gimp->environ_table = gimp_environ_table_new ();
|
||||
|
||||
gimp->plug_in_debug = NULL;
|
||||
|
@ -432,6 +434,12 @@ gimp_finalize (GObject *object)
|
|||
gimp->environ_table = NULL;
|
||||
}
|
||||
|
||||
if (gimp->interpreter_db)
|
||||
{
|
||||
g_object_unref (gimp->interpreter_db);
|
||||
gimp->interpreter_db = NULL;
|
||||
}
|
||||
|
||||
if (gimp->module_db)
|
||||
gimp_modules_exit (gimp);
|
||||
|
||||
|
@ -635,6 +643,12 @@ gimp_real_initialize (Gimp *gimp,
|
|||
(* status_callback) (_("Procedural Database"), NULL, -1);
|
||||
procedural_db_init_procs (gimp, status_callback);
|
||||
|
||||
(* status_callback) (_("Plug-In Interpreters"), "", -1);
|
||||
|
||||
path = gimp_config_path_expand (gimp->config->interpreter_path, TRUE, NULL);
|
||||
gimp_interpreter_db_load (gimp->interpreter_db, path);
|
||||
g_free (path);
|
||||
|
||||
(* status_callback) (_("Plug-In Environment"), "", -1);
|
||||
|
||||
path = gimp_config_path_expand (gimp->config->environ_path, TRUE, NULL);
|
||||
|
|
|
@ -81,6 +81,7 @@ struct _Gimp
|
|||
PlugInProcDef *last_plug_in;
|
||||
|
||||
PlugInShm *plug_in_shm;
|
||||
GimpInterpreterDB *interpreter_db;
|
||||
GimpEnvironTable *environ_table;
|
||||
GimpPlugInDebug *plug_in_debug;
|
||||
|
||||
|
|
|
@ -0,0 +1,767 @@
|
|||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* gimpinterpreterdb.c
|
||||
* (C) 2005 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The binfmt_misc bits are derived from linux/fs/binfmt_misc.c
|
||||
* Copyright (C) 1997 Richard Günther
|
||||
*/
|
||||
|
||||
/*
|
||||
* The sh-bang code is derived from linux/fs/binfmt_script.c
|
||||
* Copyright (C) 1996 Martin von Löwis
|
||||
* original #!-checking implemented by tytso.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifndef _O_BINARY
|
||||
#define _O_BINARY 0
|
||||
#endif
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gimpinterpreterdb.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
#define BUFSIZE 4096
|
||||
|
||||
|
||||
typedef struct _GimpInterpreterMagic GimpInterpreterMagic;
|
||||
|
||||
struct _GimpInterpreterMagic
|
||||
{
|
||||
gulong offset;
|
||||
gchar *magic;
|
||||
gchar *mask;
|
||||
guint size;
|
||||
gchar *program;
|
||||
};
|
||||
|
||||
|
||||
static void gimp_interpreter_db_class_init (GimpInterpreterDBClass *class);
|
||||
static void gimp_interpreter_db_init (GimpInterpreterDB *db);
|
||||
|
||||
static void gimp_interpreter_db_finalize (GObject *object);
|
||||
|
||||
static void gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
|
||||
gpointer user_data);
|
||||
|
||||
static void gimp_interpreter_db_add_program (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer);
|
||||
static void gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer);
|
||||
|
||||
static gboolean gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
|
||||
gchar **tokens);
|
||||
static gboolean gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
|
||||
gchar **tokens);
|
||||
|
||||
static void gimp_interpreter_db_clear_magics (GimpInterpreterDB *db);
|
||||
|
||||
static void gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db);
|
||||
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
|
||||
|
||||
GType
|
||||
gimp_interpreter_db_get_type (void)
|
||||
{
|
||||
static GType interpreter_db_type = 0;
|
||||
|
||||
if (! interpreter_db_type)
|
||||
{
|
||||
static const GTypeInfo interpreter_db_info =
|
||||
{
|
||||
sizeof (GimpInterpreterDBClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) gimp_interpreter_db_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (GimpInterpreterDB),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) gimp_interpreter_db_init,
|
||||
};
|
||||
|
||||
interpreter_db_type = g_type_register_static (G_TYPE_OBJECT,
|
||||
"GimpInterpreterDB",
|
||||
&interpreter_db_info, 0);
|
||||
}
|
||||
|
||||
return interpreter_db_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_class_init (GimpInterpreterDBClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
|
||||
object_class->finalize = gimp_interpreter_db_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_init (GimpInterpreterDB *db)
|
||||
{
|
||||
db->programs = NULL;
|
||||
|
||||
db->magics = NULL;
|
||||
db->magic_names = NULL;
|
||||
|
||||
db->extensions = NULL;
|
||||
db->extension_names = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_finalize (GObject *object)
|
||||
{
|
||||
GimpInterpreterDB *db;
|
||||
|
||||
db = GIMP_INTERPRETER_DB (object);
|
||||
|
||||
gimp_interpreter_db_clear (db);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GimpInterpreterDB *
|
||||
gimp_interpreter_db_new (void)
|
||||
{
|
||||
return g_object_new (GIMP_TYPE_INTERPRETER_DB, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_interpreter_db_load (GimpInterpreterDB *db,
|
||||
const gchar *interp_path)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
|
||||
|
||||
gimp_interpreter_db_clear (db);
|
||||
|
||||
db->programs = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
db->magic_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
db->extension_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
gimp_datafiles_read_directories (interp_path,
|
||||
G_FILE_TEST_EXISTS,
|
||||
gimp_interpreter_db_load_interp_file,
|
||||
db);
|
||||
|
||||
gimp_interpreter_db_resolve_programs (db);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_interpreter_db_clear (GimpInterpreterDB *db)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
|
||||
|
||||
if (db->magic_names)
|
||||
{
|
||||
g_hash_table_destroy (db->magic_names);
|
||||
db->magic_names = NULL;
|
||||
}
|
||||
|
||||
if (db->extension_names)
|
||||
{
|
||||
g_hash_table_destroy (db->extension_names);
|
||||
db->extension_names = NULL;
|
||||
}
|
||||
|
||||
if (db->programs)
|
||||
{
|
||||
g_hash_table_destroy (db->programs);
|
||||
db->programs = NULL;
|
||||
}
|
||||
|
||||
if (db->extensions)
|
||||
{
|
||||
g_hash_table_destroy (db->extensions);
|
||||
db->extensions = NULL;
|
||||
}
|
||||
|
||||
gimp_interpreter_db_clear_magics (db);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
|
||||
gpointer user_data)
|
||||
{
|
||||
GimpInterpreterDB *db;
|
||||
FILE *interp_file;
|
||||
gchar buffer[4096];
|
||||
gsize len;
|
||||
|
||||
db = GIMP_INTERPRETER_DB (user_data);
|
||||
|
||||
interp_file = g_fopen (file_data->filename, "r");
|
||||
if (! interp_file)
|
||||
return;
|
||||
|
||||
while (fgets (buffer, sizeof (buffer), interp_file))
|
||||
{
|
||||
/* Skip comments */
|
||||
if (buffer[0] == '#')
|
||||
continue;
|
||||
|
||||
len = strlen (buffer) - 1;
|
||||
|
||||
/* Skip too long lines */
|
||||
if (buffer[len] != '\n')
|
||||
continue;
|
||||
|
||||
buffer[len] = '\0';
|
||||
|
||||
if (g_ascii_isalnum (buffer[0]) || (buffer[0] == '/'))
|
||||
gimp_interpreter_db_add_program (db, file_data, buffer);
|
||||
else if (! g_ascii_isspace (buffer[0]) && (buffer[0] != '\0'))
|
||||
gimp_interpreter_db_add_binfmt_misc (db, file_data, buffer);
|
||||
}
|
||||
|
||||
fclose (interp_file);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_add_program (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer)
|
||||
{
|
||||
gchar *name, *program, *p;
|
||||
|
||||
p = strchr (buffer, '=');
|
||||
if (! p)
|
||||
return;
|
||||
|
||||
*p = '\0';
|
||||
|
||||
name = buffer;
|
||||
program = p + 1;
|
||||
|
||||
if (! g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
|
||||
{
|
||||
g_message (_("Bad interpreter referenced in interpreter file %s: %s"),
|
||||
gimp_filename_to_utf8 (file_data->filename),
|
||||
gimp_filename_to_utf8 (program));
|
||||
return;
|
||||
}
|
||||
|
||||
if (! g_hash_table_lookup (db->programs, name))
|
||||
g_hash_table_insert (db->programs, g_strdup (name), g_strdup (program));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer)
|
||||
{
|
||||
gchar **tokens = NULL;
|
||||
gchar *name, *type, *program;
|
||||
gsize count;
|
||||
gchar del[2];
|
||||
|
||||
count = strlen (buffer);
|
||||
|
||||
if ((count < 10) || (count > 255))
|
||||
goto bail;
|
||||
|
||||
del[0] = *buffer;
|
||||
del[1] = '\0';
|
||||
|
||||
memset (buffer + count, del[0], 8);
|
||||
|
||||
tokens = g_strsplit (buffer + 1, del, -1);
|
||||
|
||||
name = tokens[0];
|
||||
type = tokens[1];
|
||||
program = tokens[5];
|
||||
|
||||
if (name[0] == '\0' || program == '\0' || type[0] == '\0' || type[1] != '\0')
|
||||
goto bail;
|
||||
|
||||
switch (type[0])
|
||||
{
|
||||
case 'E':
|
||||
if (! gimp_interpreter_db_add_extension (db, tokens))
|
||||
goto bail;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (! gimp_interpreter_db_add_magic (db, tokens))
|
||||
goto bail;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto bail;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
bail:
|
||||
g_message (_("Bad binary format string in interpreter file %s"),
|
||||
gimp_filename_to_utf8 (file_data->filename));
|
||||
|
||||
out:
|
||||
g_strfreev (tokens);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
|
||||
gchar **tokens)
|
||||
{
|
||||
gchar *name, *extension, *program;
|
||||
|
||||
name = tokens[0];
|
||||
extension = tokens[3];
|
||||
program = tokens[5];
|
||||
|
||||
if (! g_hash_table_lookup (db->extension_names, name))
|
||||
{
|
||||
if (extension[0] == '\0' || extension[0] == '/')
|
||||
return FALSE;
|
||||
|
||||
program = g_strdup (program);
|
||||
|
||||
g_hash_table_insert (db->extensions, g_strdup (extension), program);
|
||||
|
||||
g_hash_table_insert (db->extension_names, g_strdup (name), program);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
scanarg (gchar *s)
|
||||
{
|
||||
gchar c;
|
||||
|
||||
while ((c = *s++) != '\0')
|
||||
{
|
||||
if (c == '\\' && *s == 'x')
|
||||
{
|
||||
s++;
|
||||
|
||||
if (! g_ascii_isxdigit (*s++))
|
||||
return FALSE;
|
||||
|
||||
if (! g_ascii_isxdigit (*s++))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
unquote (gchar *from)
|
||||
{
|
||||
gchar c, *s = from, *p = from;
|
||||
|
||||
while ((c = *s++) != '\0')
|
||||
{
|
||||
if (c == '\\' && *s == 'x')
|
||||
{
|
||||
s++;
|
||||
*p = g_ascii_xdigit_value (*s++) << 4;
|
||||
*p++ |= g_ascii_xdigit_value (*s++);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
return p - from;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
|
||||
gchar **tokens)
|
||||
{
|
||||
GimpInterpreterMagic *interp_magic;
|
||||
gchar *name, *num, *magic, *mask, *program;
|
||||
gulong offset;
|
||||
guint size;
|
||||
|
||||
name = tokens[0];
|
||||
num = tokens[2];
|
||||
magic = tokens[3];
|
||||
mask = tokens[4];
|
||||
program = tokens[5];
|
||||
|
||||
if (! g_hash_table_lookup (db->magic_names, name))
|
||||
{
|
||||
if (num[0] != '\0')
|
||||
{
|
||||
offset = strtoul (num, &num, 10);
|
||||
|
||||
if (num[0] != '\0')
|
||||
return FALSE;
|
||||
|
||||
if (offset > (BUFSIZE / 4))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
offset = 0;
|
||||
|
||||
if (! scanarg (magic))
|
||||
return FALSE;
|
||||
|
||||
if (! scanarg (mask))
|
||||
return FALSE;
|
||||
|
||||
size = unquote (magic);
|
||||
|
||||
if ((size + offset) > (BUFSIZE / 2))
|
||||
return FALSE;
|
||||
|
||||
if (mask[0] == '\0')
|
||||
mask = NULL;
|
||||
else if (unquote (mask) != size)
|
||||
return FALSE;
|
||||
|
||||
interp_magic = g_new (GimpInterpreterMagic, 1);
|
||||
|
||||
interp_magic->offset = offset;
|
||||
interp_magic->magic = g_memdup (magic, size);
|
||||
interp_magic->mask = g_memdup (mask, size);
|
||||
interp_magic->size = size;
|
||||
interp_magic->program = g_strdup (program);
|
||||
|
||||
db->magics = g_slist_append (db->magics, interp_magic);
|
||||
|
||||
g_hash_table_insert (db->magic_names, g_strdup (name), interp_magic);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_clear_magics (GimpInterpreterDB *db)
|
||||
{
|
||||
GimpInterpreterMagic *magic;
|
||||
GSList *list, *last;
|
||||
|
||||
list = db->magics;
|
||||
db->magics = NULL;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
g_free (magic->magic);
|
||||
g_free (magic->mask);
|
||||
g_free (magic->program);
|
||||
g_free (magic);
|
||||
|
||||
last = list;
|
||||
list = list->next;
|
||||
|
||||
g_slist_free_1 (last);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INTERP_DEBUG
|
||||
static void
|
||||
print_kv (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("%s: %s\n", (gchar *) key, (gchar *) value);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
quote (gchar *s,
|
||||
guint size)
|
||||
{
|
||||
GString *d;
|
||||
guint i;
|
||||
|
||||
if (s == NULL)
|
||||
return "(null)";
|
||||
|
||||
d = g_string_sized_new (size * 4);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
g_string_append_printf (d, "\\x%02x", ((guint) s[i]) & 0xff);
|
||||
|
||||
return g_string_free (d, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
resolve_program (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GimpInterpreterDB *db = user_data;
|
||||
gchar *program;
|
||||
|
||||
program = g_hash_table_lookup (db->programs, value);
|
||||
|
||||
if (program != NULL)
|
||||
{
|
||||
g_free (value);
|
||||
value = g_strdup (program);
|
||||
}
|
||||
|
||||
g_hash_table_insert (db->extensions, key, value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db)
|
||||
{
|
||||
GSList *list;
|
||||
gchar *program;
|
||||
GimpInterpreterMagic *magic;
|
||||
GHashTable *extensions;
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
program = g_hash_table_lookup (db->programs, magic->program);
|
||||
|
||||
if (program != NULL)
|
||||
{
|
||||
g_free (magic->program);
|
||||
magic->program = g_strdup (program);
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
extensions = db->extensions;
|
||||
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
g_hash_table_foreach_steal (extensions, resolve_program, db);
|
||||
|
||||
g_hash_table_destroy (extensions);
|
||||
|
||||
#ifdef INTERP_DEBUG
|
||||
g_print ("Programs:\n");
|
||||
g_hash_table_foreach (db->programs, print_kv, NULL);
|
||||
|
||||
g_print ("\nExtensions:\n");
|
||||
g_hash_table_foreach (db->extensions, print_kv, NULL);
|
||||
|
||||
g_print ("\nMagics:\n");
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
GimpInterpreterMagic *magic;
|
||||
|
||||
magic = list->data;
|
||||
g_print ("program: %s, offset: %lu, magic: %s, mask: %s\n",
|
||||
magic->program, magic->offset,
|
||||
quote (magic->magic, magic->size),
|
||||
quote (magic->mask, magic->size));
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
g_print ("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_extension (GimpInterpreterDB *db,
|
||||
const gchar *program_path)
|
||||
{
|
||||
gchar *filename, *p, *program;
|
||||
|
||||
filename = g_path_get_basename (program_path);
|
||||
|
||||
p = strrchr (filename, '.');
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
program = g_hash_table_lookup (db->extensions, p + 1);
|
||||
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_sh_bang (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar *buffer,
|
||||
gssize len,
|
||||
gchar **interp_arg)
|
||||
{
|
||||
gchar *cp, *name, *program;
|
||||
|
||||
cp = strchr (buffer, '\n');
|
||||
if (! cp)
|
||||
cp = buffer + len - 1;
|
||||
|
||||
*cp = '\0';
|
||||
|
||||
while (cp > buffer)
|
||||
{
|
||||
cp--;
|
||||
if ((*cp == ' ') || (*cp == '\t'))
|
||||
*cp = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (cp = buffer + 2; (*cp == ' ') || (*cp == '\t'); cp++);
|
||||
|
||||
if (*cp == '\0')
|
||||
return NULL;
|
||||
|
||||
name = cp;
|
||||
|
||||
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
|
||||
/* nothing */ ;
|
||||
|
||||
while ((*cp == ' ') || (*cp == '\t'))
|
||||
*cp++ = '\0';
|
||||
|
||||
if (*cp)
|
||||
{
|
||||
if (strcmp ("/usr/bin/env", name) == 0)
|
||||
{
|
||||
program = g_hash_table_lookup (db->programs, cp);
|
||||
if (program)
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
*interp_arg = g_strdup (cp);
|
||||
}
|
||||
|
||||
program = g_hash_table_lookup (db->programs, name);
|
||||
if (! program)
|
||||
program = name;
|
||||
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_magic (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar *buffer)
|
||||
{
|
||||
GSList *list;
|
||||
GimpInterpreterMagic *magic;
|
||||
gchar *s;
|
||||
guint i;
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
s = buffer + magic->offset;
|
||||
|
||||
if (magic->mask)
|
||||
{
|
||||
for (i = 0; i < magic->size; i++)
|
||||
if ((*s++ ^ magic->magic[i]) & magic->mask[i])
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < magic->size; i++)
|
||||
if ((*s++ ^ magic->magic[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == magic->size)
|
||||
return g_strdup (magic->program);
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return resolve_extension (db, program_path);
|
||||
}
|
||||
|
||||
gchar *
|
||||
gimp_interpreter_db_resolve (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar **interp_arg)
|
||||
{
|
||||
gint fd;
|
||||
gssize len;
|
||||
gchar buffer[BUFSIZE];
|
||||
|
||||
*interp_arg = NULL;
|
||||
|
||||
fd = g_open (program_path, O_RDONLY | _O_BINARY, 0);
|
||||
|
||||
if (fd == -1)
|
||||
return resolve_extension (db, program_path);
|
||||
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
len = read (fd, buffer, sizeof (buffer));
|
||||
close (fd);
|
||||
|
||||
if (len <= 0)
|
||||
return resolve_extension (db, program_path);
|
||||
|
||||
if (len > 3 && buffer[0] == '#' && buffer[1] == '!')
|
||||
return resolve_sh_bang (db, program_path, buffer, len, interp_arg);
|
||||
|
||||
return resolve_magic (db, program_path, buffer);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* gimpinterpreterdb.h
|
||||
* (C) 2005 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GIMP_INTERPRETER_DB_H__
|
||||
#define __GIMP_INTERPRETER_DB_H__
|
||||
|
||||
|
||||
#define GIMP_TYPE_INTERPRETER_DB (gimp_interpreter_db_get_type ())
|
||||
#define GIMP_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDB))
|
||||
#define GIMP_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
|
||||
#define GIMP_IS_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INTERPRETER_DB))
|
||||
#define GIMP_IS_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INTERPRETER_DB))
|
||||
#define GIMP_INTERPRETER_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
|
||||
|
||||
|
||||
typedef struct _GimpInterpreterDBClass GimpInterpreterDBClass;
|
||||
|
||||
struct _GimpInterpreterDB
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GHashTable *programs;
|
||||
|
||||
GSList *magics;
|
||||
GHashTable *magic_names;
|
||||
|
||||
GHashTable *extensions;
|
||||
GHashTable *extension_names;
|
||||
};
|
||||
|
||||
struct _GimpInterpreterDBClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType gimp_interpreter_db_get_type (void) G_GNUC_CONST;
|
||||
GimpInterpreterDB * gimp_interpreter_db_new (void);
|
||||
|
||||
void gimp_interpreter_db_load (GimpInterpreterDB *db,
|
||||
const gchar *interp_path);
|
||||
|
||||
void gimp_interpreter_db_clear (GimpInterpreterDB *db);
|
||||
|
||||
gchar * gimp_interpreter_db_resolve (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar **interp_arg);
|
||||
|
||||
|
||||
#endif /* __GIMP_INTERPRETER_DB_H__ */
|
|
@ -2396,6 +2396,10 @@ prefs_dialog_new (Gimp *gimp,
|
|||
GIMP_HELP_PREFS_FOLDERS_MODULES,
|
||||
N_("Select Module Folders"),
|
||||
"module-path", NULL },
|
||||
{ N_("Interpreters"), N_("Interpreter Folders"), "folders-interp.png",
|
||||
GIMP_HELP_PREFS_FOLDERS_INTERPRETERS,
|
||||
N_("Select Interpreter Folders"),
|
||||
"interpreter-path", NULL },
|
||||
{ N_("Environment"), N_("Environment Folders"), "folders-environ.png",
|
||||
GIMP_HELP_PREFS_FOLDERS_ENVIRONMENT,
|
||||
N_("Select Environment Folders"),
|
||||
|
|
|
@ -243,6 +243,16 @@ tree_items[] =
|
|||
"during initialization."),
|
||||
TREE_ITEM_MKDIR
|
||||
},
|
||||
{
|
||||
TRUE, "interpreters",
|
||||
N_("This folder is used to store configuration for user "
|
||||
"created, temporary, or otherwise non-system-supported "
|
||||
"plug-in interpreters. The GIMP checks this folder in "
|
||||
"addition to the system-wide GIMP interpreters folder "
|
||||
"when searching for plug-in interpreter configuration "
|
||||
"files."),
|
||||
TREE_ITEM_MKDIR
|
||||
},
|
||||
{
|
||||
TRUE, "environ",
|
||||
N_("This folder is used to store user created, temporary, "
|
||||
|
|
|
@ -0,0 +1,767 @@
|
|||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* gimpinterpreterdb.c
|
||||
* (C) 2005 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The binfmt_misc bits are derived from linux/fs/binfmt_misc.c
|
||||
* Copyright (C) 1997 Richard Günther
|
||||
*/
|
||||
|
||||
/*
|
||||
* The sh-bang code is derived from linux/fs/binfmt_script.c
|
||||
* Copyright (C) 1996 Martin von Löwis
|
||||
* original #!-checking implemented by tytso.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifndef _O_BINARY
|
||||
#define _O_BINARY 0
|
||||
#endif
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gimpinterpreterdb.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
#define BUFSIZE 4096
|
||||
|
||||
|
||||
typedef struct _GimpInterpreterMagic GimpInterpreterMagic;
|
||||
|
||||
struct _GimpInterpreterMagic
|
||||
{
|
||||
gulong offset;
|
||||
gchar *magic;
|
||||
gchar *mask;
|
||||
guint size;
|
||||
gchar *program;
|
||||
};
|
||||
|
||||
|
||||
static void gimp_interpreter_db_class_init (GimpInterpreterDBClass *class);
|
||||
static void gimp_interpreter_db_init (GimpInterpreterDB *db);
|
||||
|
||||
static void gimp_interpreter_db_finalize (GObject *object);
|
||||
|
||||
static void gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
|
||||
gpointer user_data);
|
||||
|
||||
static void gimp_interpreter_db_add_program (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer);
|
||||
static void gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer);
|
||||
|
||||
static gboolean gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
|
||||
gchar **tokens);
|
||||
static gboolean gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
|
||||
gchar **tokens);
|
||||
|
||||
static void gimp_interpreter_db_clear_magics (GimpInterpreterDB *db);
|
||||
|
||||
static void gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db);
|
||||
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
|
||||
|
||||
GType
|
||||
gimp_interpreter_db_get_type (void)
|
||||
{
|
||||
static GType interpreter_db_type = 0;
|
||||
|
||||
if (! interpreter_db_type)
|
||||
{
|
||||
static const GTypeInfo interpreter_db_info =
|
||||
{
|
||||
sizeof (GimpInterpreterDBClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) gimp_interpreter_db_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (GimpInterpreterDB),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) gimp_interpreter_db_init,
|
||||
};
|
||||
|
||||
interpreter_db_type = g_type_register_static (G_TYPE_OBJECT,
|
||||
"GimpInterpreterDB",
|
||||
&interpreter_db_info, 0);
|
||||
}
|
||||
|
||||
return interpreter_db_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_class_init (GimpInterpreterDBClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
|
||||
object_class->finalize = gimp_interpreter_db_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_init (GimpInterpreterDB *db)
|
||||
{
|
||||
db->programs = NULL;
|
||||
|
||||
db->magics = NULL;
|
||||
db->magic_names = NULL;
|
||||
|
||||
db->extensions = NULL;
|
||||
db->extension_names = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_finalize (GObject *object)
|
||||
{
|
||||
GimpInterpreterDB *db;
|
||||
|
||||
db = GIMP_INTERPRETER_DB (object);
|
||||
|
||||
gimp_interpreter_db_clear (db);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GimpInterpreterDB *
|
||||
gimp_interpreter_db_new (void)
|
||||
{
|
||||
return g_object_new (GIMP_TYPE_INTERPRETER_DB, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_interpreter_db_load (GimpInterpreterDB *db,
|
||||
const gchar *interp_path)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
|
||||
|
||||
gimp_interpreter_db_clear (db);
|
||||
|
||||
db->programs = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
db->magic_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
db->extension_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
gimp_datafiles_read_directories (interp_path,
|
||||
G_FILE_TEST_EXISTS,
|
||||
gimp_interpreter_db_load_interp_file,
|
||||
db);
|
||||
|
||||
gimp_interpreter_db_resolve_programs (db);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_interpreter_db_clear (GimpInterpreterDB *db)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
|
||||
|
||||
if (db->magic_names)
|
||||
{
|
||||
g_hash_table_destroy (db->magic_names);
|
||||
db->magic_names = NULL;
|
||||
}
|
||||
|
||||
if (db->extension_names)
|
||||
{
|
||||
g_hash_table_destroy (db->extension_names);
|
||||
db->extension_names = NULL;
|
||||
}
|
||||
|
||||
if (db->programs)
|
||||
{
|
||||
g_hash_table_destroy (db->programs);
|
||||
db->programs = NULL;
|
||||
}
|
||||
|
||||
if (db->extensions)
|
||||
{
|
||||
g_hash_table_destroy (db->extensions);
|
||||
db->extensions = NULL;
|
||||
}
|
||||
|
||||
gimp_interpreter_db_clear_magics (db);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
|
||||
gpointer user_data)
|
||||
{
|
||||
GimpInterpreterDB *db;
|
||||
FILE *interp_file;
|
||||
gchar buffer[4096];
|
||||
gsize len;
|
||||
|
||||
db = GIMP_INTERPRETER_DB (user_data);
|
||||
|
||||
interp_file = g_fopen (file_data->filename, "r");
|
||||
if (! interp_file)
|
||||
return;
|
||||
|
||||
while (fgets (buffer, sizeof (buffer), interp_file))
|
||||
{
|
||||
/* Skip comments */
|
||||
if (buffer[0] == '#')
|
||||
continue;
|
||||
|
||||
len = strlen (buffer) - 1;
|
||||
|
||||
/* Skip too long lines */
|
||||
if (buffer[len] != '\n')
|
||||
continue;
|
||||
|
||||
buffer[len] = '\0';
|
||||
|
||||
if (g_ascii_isalnum (buffer[0]) || (buffer[0] == '/'))
|
||||
gimp_interpreter_db_add_program (db, file_data, buffer);
|
||||
else if (! g_ascii_isspace (buffer[0]) && (buffer[0] != '\0'))
|
||||
gimp_interpreter_db_add_binfmt_misc (db, file_data, buffer);
|
||||
}
|
||||
|
||||
fclose (interp_file);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_add_program (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer)
|
||||
{
|
||||
gchar *name, *program, *p;
|
||||
|
||||
p = strchr (buffer, '=');
|
||||
if (! p)
|
||||
return;
|
||||
|
||||
*p = '\0';
|
||||
|
||||
name = buffer;
|
||||
program = p + 1;
|
||||
|
||||
if (! g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
|
||||
{
|
||||
g_message (_("Bad interpreter referenced in interpreter file %s: %s"),
|
||||
gimp_filename_to_utf8 (file_data->filename),
|
||||
gimp_filename_to_utf8 (program));
|
||||
return;
|
||||
}
|
||||
|
||||
if (! g_hash_table_lookup (db->programs, name))
|
||||
g_hash_table_insert (db->programs, g_strdup (name), g_strdup (program));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
|
||||
const GimpDatafileData *file_data,
|
||||
gchar *buffer)
|
||||
{
|
||||
gchar **tokens = NULL;
|
||||
gchar *name, *type, *program;
|
||||
gsize count;
|
||||
gchar del[2];
|
||||
|
||||
count = strlen (buffer);
|
||||
|
||||
if ((count < 10) || (count > 255))
|
||||
goto bail;
|
||||
|
||||
del[0] = *buffer;
|
||||
del[1] = '\0';
|
||||
|
||||
memset (buffer + count, del[0], 8);
|
||||
|
||||
tokens = g_strsplit (buffer + 1, del, -1);
|
||||
|
||||
name = tokens[0];
|
||||
type = tokens[1];
|
||||
program = tokens[5];
|
||||
|
||||
if (name[0] == '\0' || program == '\0' || type[0] == '\0' || type[1] != '\0')
|
||||
goto bail;
|
||||
|
||||
switch (type[0])
|
||||
{
|
||||
case 'E':
|
||||
if (! gimp_interpreter_db_add_extension (db, tokens))
|
||||
goto bail;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (! gimp_interpreter_db_add_magic (db, tokens))
|
||||
goto bail;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto bail;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
bail:
|
||||
g_message (_("Bad binary format string in interpreter file %s"),
|
||||
gimp_filename_to_utf8 (file_data->filename));
|
||||
|
||||
out:
|
||||
g_strfreev (tokens);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
|
||||
gchar **tokens)
|
||||
{
|
||||
gchar *name, *extension, *program;
|
||||
|
||||
name = tokens[0];
|
||||
extension = tokens[3];
|
||||
program = tokens[5];
|
||||
|
||||
if (! g_hash_table_lookup (db->extension_names, name))
|
||||
{
|
||||
if (extension[0] == '\0' || extension[0] == '/')
|
||||
return FALSE;
|
||||
|
||||
program = g_strdup (program);
|
||||
|
||||
g_hash_table_insert (db->extensions, g_strdup (extension), program);
|
||||
|
||||
g_hash_table_insert (db->extension_names, g_strdup (name), program);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
scanarg (gchar *s)
|
||||
{
|
||||
gchar c;
|
||||
|
||||
while ((c = *s++) != '\0')
|
||||
{
|
||||
if (c == '\\' && *s == 'x')
|
||||
{
|
||||
s++;
|
||||
|
||||
if (! g_ascii_isxdigit (*s++))
|
||||
return FALSE;
|
||||
|
||||
if (! g_ascii_isxdigit (*s++))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
unquote (gchar *from)
|
||||
{
|
||||
gchar c, *s = from, *p = from;
|
||||
|
||||
while ((c = *s++) != '\0')
|
||||
{
|
||||
if (c == '\\' && *s == 'x')
|
||||
{
|
||||
s++;
|
||||
*p = g_ascii_xdigit_value (*s++) << 4;
|
||||
*p++ |= g_ascii_xdigit_value (*s++);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
return p - from;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
|
||||
gchar **tokens)
|
||||
{
|
||||
GimpInterpreterMagic *interp_magic;
|
||||
gchar *name, *num, *magic, *mask, *program;
|
||||
gulong offset;
|
||||
guint size;
|
||||
|
||||
name = tokens[0];
|
||||
num = tokens[2];
|
||||
magic = tokens[3];
|
||||
mask = tokens[4];
|
||||
program = tokens[5];
|
||||
|
||||
if (! g_hash_table_lookup (db->magic_names, name))
|
||||
{
|
||||
if (num[0] != '\0')
|
||||
{
|
||||
offset = strtoul (num, &num, 10);
|
||||
|
||||
if (num[0] != '\0')
|
||||
return FALSE;
|
||||
|
||||
if (offset > (BUFSIZE / 4))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
offset = 0;
|
||||
|
||||
if (! scanarg (magic))
|
||||
return FALSE;
|
||||
|
||||
if (! scanarg (mask))
|
||||
return FALSE;
|
||||
|
||||
size = unquote (magic);
|
||||
|
||||
if ((size + offset) > (BUFSIZE / 2))
|
||||
return FALSE;
|
||||
|
||||
if (mask[0] == '\0')
|
||||
mask = NULL;
|
||||
else if (unquote (mask) != size)
|
||||
return FALSE;
|
||||
|
||||
interp_magic = g_new (GimpInterpreterMagic, 1);
|
||||
|
||||
interp_magic->offset = offset;
|
||||
interp_magic->magic = g_memdup (magic, size);
|
||||
interp_magic->mask = g_memdup (mask, size);
|
||||
interp_magic->size = size;
|
||||
interp_magic->program = g_strdup (program);
|
||||
|
||||
db->magics = g_slist_append (db->magics, interp_magic);
|
||||
|
||||
g_hash_table_insert (db->magic_names, g_strdup (name), interp_magic);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_clear_magics (GimpInterpreterDB *db)
|
||||
{
|
||||
GimpInterpreterMagic *magic;
|
||||
GSList *list, *last;
|
||||
|
||||
list = db->magics;
|
||||
db->magics = NULL;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
g_free (magic->magic);
|
||||
g_free (magic->mask);
|
||||
g_free (magic->program);
|
||||
g_free (magic);
|
||||
|
||||
last = list;
|
||||
list = list->next;
|
||||
|
||||
g_slist_free_1 (last);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INTERP_DEBUG
|
||||
static void
|
||||
print_kv (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("%s: %s\n", (gchar *) key, (gchar *) value);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
quote (gchar *s,
|
||||
guint size)
|
||||
{
|
||||
GString *d;
|
||||
guint i;
|
||||
|
||||
if (s == NULL)
|
||||
return "(null)";
|
||||
|
||||
d = g_string_sized_new (size * 4);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
g_string_append_printf (d, "\\x%02x", ((guint) s[i]) & 0xff);
|
||||
|
||||
return g_string_free (d, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
resolve_program (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GimpInterpreterDB *db = user_data;
|
||||
gchar *program;
|
||||
|
||||
program = g_hash_table_lookup (db->programs, value);
|
||||
|
||||
if (program != NULL)
|
||||
{
|
||||
g_free (value);
|
||||
value = g_strdup (program);
|
||||
}
|
||||
|
||||
g_hash_table_insert (db->extensions, key, value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db)
|
||||
{
|
||||
GSList *list;
|
||||
gchar *program;
|
||||
GimpInterpreterMagic *magic;
|
||||
GHashTable *extensions;
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
program = g_hash_table_lookup (db->programs, magic->program);
|
||||
|
||||
if (program != NULL)
|
||||
{
|
||||
g_free (magic->program);
|
||||
magic->program = g_strdup (program);
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
extensions = db->extensions;
|
||||
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
g_hash_table_foreach_steal (extensions, resolve_program, db);
|
||||
|
||||
g_hash_table_destroy (extensions);
|
||||
|
||||
#ifdef INTERP_DEBUG
|
||||
g_print ("Programs:\n");
|
||||
g_hash_table_foreach (db->programs, print_kv, NULL);
|
||||
|
||||
g_print ("\nExtensions:\n");
|
||||
g_hash_table_foreach (db->extensions, print_kv, NULL);
|
||||
|
||||
g_print ("\nMagics:\n");
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
GimpInterpreterMagic *magic;
|
||||
|
||||
magic = list->data;
|
||||
g_print ("program: %s, offset: %lu, magic: %s, mask: %s\n",
|
||||
magic->program, magic->offset,
|
||||
quote (magic->magic, magic->size),
|
||||
quote (magic->mask, magic->size));
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
g_print ("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_extension (GimpInterpreterDB *db,
|
||||
const gchar *program_path)
|
||||
{
|
||||
gchar *filename, *p, *program;
|
||||
|
||||
filename = g_path_get_basename (program_path);
|
||||
|
||||
p = strrchr (filename, '.');
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
program = g_hash_table_lookup (db->extensions, p + 1);
|
||||
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_sh_bang (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar *buffer,
|
||||
gssize len,
|
||||
gchar **interp_arg)
|
||||
{
|
||||
gchar *cp, *name, *program;
|
||||
|
||||
cp = strchr (buffer, '\n');
|
||||
if (! cp)
|
||||
cp = buffer + len - 1;
|
||||
|
||||
*cp = '\0';
|
||||
|
||||
while (cp > buffer)
|
||||
{
|
||||
cp--;
|
||||
if ((*cp == ' ') || (*cp == '\t'))
|
||||
*cp = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (cp = buffer + 2; (*cp == ' ') || (*cp == '\t'); cp++);
|
||||
|
||||
if (*cp == '\0')
|
||||
return NULL;
|
||||
|
||||
name = cp;
|
||||
|
||||
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
|
||||
/* nothing */ ;
|
||||
|
||||
while ((*cp == ' ') || (*cp == '\t'))
|
||||
*cp++ = '\0';
|
||||
|
||||
if (*cp)
|
||||
{
|
||||
if (strcmp ("/usr/bin/env", name) == 0)
|
||||
{
|
||||
program = g_hash_table_lookup (db->programs, cp);
|
||||
if (program)
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
*interp_arg = g_strdup (cp);
|
||||
}
|
||||
|
||||
program = g_hash_table_lookup (db->programs, name);
|
||||
if (! program)
|
||||
program = name;
|
||||
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_magic (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar *buffer)
|
||||
{
|
||||
GSList *list;
|
||||
GimpInterpreterMagic *magic;
|
||||
gchar *s;
|
||||
guint i;
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
s = buffer + magic->offset;
|
||||
|
||||
if (magic->mask)
|
||||
{
|
||||
for (i = 0; i < magic->size; i++)
|
||||
if ((*s++ ^ magic->magic[i]) & magic->mask[i])
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < magic->size; i++)
|
||||
if ((*s++ ^ magic->magic[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == magic->size)
|
||||
return g_strdup (magic->program);
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return resolve_extension (db, program_path);
|
||||
}
|
||||
|
||||
gchar *
|
||||
gimp_interpreter_db_resolve (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar **interp_arg)
|
||||
{
|
||||
gint fd;
|
||||
gssize len;
|
||||
gchar buffer[BUFSIZE];
|
||||
|
||||
*interp_arg = NULL;
|
||||
|
||||
fd = g_open (program_path, O_RDONLY | _O_BINARY, 0);
|
||||
|
||||
if (fd == -1)
|
||||
return resolve_extension (db, program_path);
|
||||
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
len = read (fd, buffer, sizeof (buffer));
|
||||
close (fd);
|
||||
|
||||
if (len <= 0)
|
||||
return resolve_extension (db, program_path);
|
||||
|
||||
if (len > 3 && buffer[0] == '#' && buffer[1] == '!')
|
||||
return resolve_sh_bang (db, program_path, buffer, len, interp_arg);
|
||||
|
||||
return resolve_magic (db, program_path, buffer);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* gimpinterpreterdb.h
|
||||
* (C) 2005 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GIMP_INTERPRETER_DB_H__
|
||||
#define __GIMP_INTERPRETER_DB_H__
|
||||
|
||||
|
||||
#define GIMP_TYPE_INTERPRETER_DB (gimp_interpreter_db_get_type ())
|
||||
#define GIMP_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDB))
|
||||
#define GIMP_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
|
||||
#define GIMP_IS_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INTERPRETER_DB))
|
||||
#define GIMP_IS_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INTERPRETER_DB))
|
||||
#define GIMP_INTERPRETER_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
|
||||
|
||||
|
||||
typedef struct _GimpInterpreterDBClass GimpInterpreterDBClass;
|
||||
|
||||
struct _GimpInterpreterDB
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GHashTable *programs;
|
||||
|
||||
GSList *magics;
|
||||
GHashTable *magic_names;
|
||||
|
||||
GHashTable *extensions;
|
||||
GHashTable *extension_names;
|
||||
};
|
||||
|
||||
struct _GimpInterpreterDBClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType gimp_interpreter_db_get_type (void) G_GNUC_CONST;
|
||||
GimpInterpreterDB * gimp_interpreter_db_new (void);
|
||||
|
||||
void gimp_interpreter_db_load (GimpInterpreterDB *db,
|
||||
const gchar *interp_path);
|
||||
|
||||
void gimp_interpreter_db_clear (GimpInterpreterDB *db);
|
||||
|
||||
gchar * gimp_interpreter_db_resolve (GimpInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar **interp_arg);
|
||||
|
||||
|
||||
#endif /* __GIMP_INTERPRETER_DB_H__ */
|
|
@ -73,6 +73,7 @@
|
|||
#include "core/gimp.h"
|
||||
#include "core/gimpcontext.h"
|
||||
#include "core/gimpenvirontable.h"
|
||||
#include "core/gimpinterpreterdb.h"
|
||||
#include "core/gimpprogress.h"
|
||||
|
||||
#include "plug-in.h"
|
||||
|
@ -337,7 +338,9 @@ plug_in_open (PlugIn *plug_in)
|
|||
gint my_read[2];
|
||||
gint my_write[2];
|
||||
gchar **envp;
|
||||
gchar *args[7], **argv, **debug_argv;
|
||||
gchar *args[9], **argv, **debug_argv;
|
||||
gint argc;
|
||||
gchar *interp, *interp_arg;
|
||||
gchar *read_fd, *write_fd;
|
||||
gchar *mode, *stm;
|
||||
GError *error = NULL;
|
||||
|
@ -417,13 +420,23 @@ plug_in_open (PlugIn *plug_in)
|
|||
|
||||
stm = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
|
||||
|
||||
args[0] = plug_in->prog;
|
||||
args[1] = "-gimp";
|
||||
args[2] = read_fd;
|
||||
args[3] = write_fd;
|
||||
args[4] = mode;
|
||||
args[5] = stm;
|
||||
args[6] = NULL;
|
||||
interp = gimp_interpreter_db_resolve (plug_in->gimp->interpreter_db,
|
||||
plug_in->prog, &interp_arg);
|
||||
|
||||
argc = 0;
|
||||
|
||||
if (interp)
|
||||
args[argc++] = interp;
|
||||
if (interp_arg)
|
||||
args[argc++] = interp_arg;
|
||||
|
||||
args[argc++] = plug_in->prog;
|
||||
args[argc++] = "-gimp";
|
||||
args[argc++] = read_fd;
|
||||
args[argc++] = write_fd;
|
||||
args[argc++] = mode;
|
||||
args[argc++] = stm;
|
||||
args[argc++] = NULL;
|
||||
|
||||
argv = args;
|
||||
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
|
||||
|
@ -497,6 +510,9 @@ cleanup:
|
|||
g_free (write_fd);
|
||||
g_free (stm);
|
||||
|
||||
g_free (interp);
|
||||
g_free (interp_arg);
|
||||
|
||||
return plug_in->open;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "core/gimp.h"
|
||||
#include "core/gimpcontext.h"
|
||||
#include "core/gimpenvirontable.h"
|
||||
#include "core/gimpinterpreterdb.h"
|
||||
#include "core/gimpprogress.h"
|
||||
|
||||
#include "plug-in.h"
|
||||
|
@ -337,7 +338,9 @@ plug_in_open (PlugIn *plug_in)
|
|||
gint my_read[2];
|
||||
gint my_write[2];
|
||||
gchar **envp;
|
||||
gchar *args[7], **argv, **debug_argv;
|
||||
gchar *args[9], **argv, **debug_argv;
|
||||
gint argc;
|
||||
gchar *interp, *interp_arg;
|
||||
gchar *read_fd, *write_fd;
|
||||
gchar *mode, *stm;
|
||||
GError *error = NULL;
|
||||
|
@ -417,13 +420,23 @@ plug_in_open (PlugIn *plug_in)
|
|||
|
||||
stm = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
|
||||
|
||||
args[0] = plug_in->prog;
|
||||
args[1] = "-gimp";
|
||||
args[2] = read_fd;
|
||||
args[3] = write_fd;
|
||||
args[4] = mode;
|
||||
args[5] = stm;
|
||||
args[6] = NULL;
|
||||
interp = gimp_interpreter_db_resolve (plug_in->gimp->interpreter_db,
|
||||
plug_in->prog, &interp_arg);
|
||||
|
||||
argc = 0;
|
||||
|
||||
if (interp)
|
||||
args[argc++] = interp;
|
||||
if (interp_arg)
|
||||
args[argc++] = interp_arg;
|
||||
|
||||
args[argc++] = plug_in->prog;
|
||||
args[argc++] = "-gimp";
|
||||
args[argc++] = read_fd;
|
||||
args[argc++] = write_fd;
|
||||
args[argc++] = mode;
|
||||
args[argc++] = stm;
|
||||
args[argc++] = NULL;
|
||||
|
||||
argv = args;
|
||||
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
|
||||
|
@ -497,6 +510,9 @@ cleanup:
|
|||
g_free (write_fd);
|
||||
g_free (stm);
|
||||
|
||||
g_free (interp);
|
||||
g_free (interp_arg);
|
||||
|
||||
return plug_in->open;
|
||||
}
|
||||
|
||||
|
|
|
@ -399,6 +399,7 @@
|
|||
#define GIMP_HELP_PREFS_FOLDERS_PLUG_INS "gimp-prefs-folders-plug-ins"
|
||||
#define GIMP_HELP_PREFS_FOLDERS_SCRIPTS "gimp-prefs-folders-scripts"
|
||||
#define GIMP_HELP_PREFS_FOLDERS_MODULES "gimp-prefs-folders-modules"
|
||||
#define GIMP_HELP_PREFS_FOLDERS_INTERPRETERS "gimp-prefs-folders-interpreters"
|
||||
#define GIMP_HELP_PREFS_FOLDERS_ENVIRONMENT "gimp-prefs-folders-environment"
|
||||
#define GIMP_HELP_PREFS_FOLDERS_THEMES "gimp-prefs-folders-themes"
|
||||
|
||||
|
|
|
@ -1647,6 +1647,7 @@ themes/Default/images/Makefile
|
|||
themes/Default/images/preferences/Makefile
|
||||
themes/Small/Makefile
|
||||
data/Makefile
|
||||
data/interpreters/Makefile
|
||||
data/environ/Makefile
|
||||
data/misc/Makefile
|
||||
data/misc/gimp.desktop.in
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Makefile.am for gimp/data
|
||||
|
||||
SUBDIRS = environ misc images brushes gradients palettes patterns
|
||||
SUBDIRS = interpreters environ misc images brushes gradients palettes patterns
|
||||
|
||||
EXTRA_DIST = \
|
||||
AUTHORS \
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Makefile.in
|
||||
Makefile
|
|
@ -0,0 +1,7 @@
|
|||
## Makefile.am for gimp/data/interpreters
|
||||
|
||||
interpretersdir = $(gimpplugindir)/interpreters
|
||||
|
||||
interpreters_DATA = default.interp
|
||||
|
||||
EXTRA_DIST = $(interpreters_DATA)
|
|
@ -0,0 +1,15 @@
|
|||
# Example entries in files like these
|
||||
|
||||
# This registers an interpreter name with a binary
|
||||
# It is matched against #! syntax and the binfmt_misc syntax
|
||||
#scm=/path/to/scm
|
||||
|
||||
# The following is the same syntax as Linux binfmt_misc
|
||||
# See Documentation/binfmt_misc.txt in the Linux kernel sources for
|
||||
# detailed information. (Right now, "flags" are noops)
|
||||
|
||||
# Register an extension
|
||||
#:Scheme-ext:E::scm::/path/to/scm:
|
||||
|
||||
# Register a magic
|
||||
#:Scheme-magic:M::\x3b\x20GIMP Scheme::scm:
|
|
@ -61,14 +61,14 @@ GIMP opts for speed over memory. However, if memory is a big issue, try to
|
|||
enable this setting. Possible values are yes and no.
|
||||
|
||||
.TP
|
||||
(num-processors 1)
|
||||
(num-processors 2)
|
||||
|
||||
On multiprocessor machines, if GIMP has been compiled with --enable-mp this
|
||||
sets how many processors GIMP should use simultaneously. This is an integer
|
||||
value.
|
||||
|
||||
.TP
|
||||
(tile-cache-size 128M)
|
||||
(tile-cache-size 256M)
|
||||
|
||||
The tile cache is used to make sure the GIMP doesn't thrash tiles between
|
||||
memory and disk. Setting this value higher will cause the GIMP to use less
|
||||
|
@ -83,7 +83,7 @@ kilobytes.
|
|||
(interpolation-type linear)
|
||||
|
||||
Sets the level of interpolation used for scaling and other transformations.
|
||||
Possible values are none, linear and cubic.
|
||||
Possible values are none, linear, cubic and lanczos.
|
||||
|
||||
.TP
|
||||
(plug-in-path "${gimp_dir}/plug-ins:${gimp_plug_in_dir}/plug-ins")
|
||||
|
@ -97,6 +97,12 @@ search.
|
|||
Sets the module search path. This is a colon-separated list of folders to
|
||||
search.
|
||||
|
||||
.TP
|
||||
(interpreter-path "${gimp_dir}/interpreters:${gimp_plug_in_dir}/interpreters")
|
||||
|
||||
Sets the interpreter search path. This is a colon-separated list of folders
|
||||
to search.
|
||||
|
||||
.TP
|
||||
(environ-path "${gimp_dir}/environ:${gimp_plug_in_dir}/environ")
|
||||
|
||||
|
@ -219,8 +225,8 @@ are yes and no.
|
|||
|
||||
.TP
|
||||
(default-image
|
||||
(width 420)
|
||||
(height 300)
|
||||
(width 377)
|
||||
(height 233)
|
||||
(unit pixels)
|
||||
(xresolution 72.000000)
|
||||
(yresolution 72.000000)
|
||||
|
@ -236,8 +242,8 @@ Sets the default image in the "File/New" dialog. This is a parameter list.
|
|||
(style intersections)
|
||||
(fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000))
|
||||
(bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000))
|
||||
(xspacing 10.000000)
|
||||
(yspacing 10.000000)
|
||||
(xspacing 32.000000)
|
||||
(yspacing 32.000000)
|
||||
(spacing-unit inches)
|
||||
(xoffset 0.000000)
|
||||
(yoffset 0.000000)
|
||||
|
@ -315,6 +321,14 @@ Possible values are yes and no.
|
|||
Generally only a concern for 8-bit displays, this sets the minimum number of
|
||||
system colors allocated for the GIMP. This is an integer value.
|
||||
|
||||
.TP
|
||||
(color-management
|
||||
(mode display)
|
||||
(display-rendering-intent perceptual)
|
||||
(simulation-rendering-intent perceptual))
|
||||
|
||||
Defines the color management behavior. This is a parameter list.
|
||||
|
||||
.TP
|
||||
(transparency-size medium-checks)
|
||||
|
||||
|
|
26
etc/gimprc
26
etc/gimprc
|
@ -39,7 +39,7 @@
|
|||
# sets how many processors GIMP should use simultaneously. This is an
|
||||
# integer value.
|
||||
#
|
||||
# (num-processors 1)
|
||||
# (num-processors 2)
|
||||
|
||||
# The tile cache is used to make sure the GIMP doesn't thrash tiles between
|
||||
# memory and disk. Setting this value higher will cause the GIMP to use less
|
||||
|
@ -50,10 +50,10 @@
|
|||
# or gigabytes. If no suffix is specified the size defaults to being
|
||||
# specified in kilobytes.
|
||||
#
|
||||
# (tile-cache-size 128M)
|
||||
# (tile-cache-size 256M)
|
||||
|
||||
# Sets the level of interpolation used for scaling and other transformations.
|
||||
# Possible values are none, linear and cubic.
|
||||
# Possible values are none, linear, cubic and lanczos.
|
||||
#
|
||||
# (interpolation-type linear)
|
||||
|
||||
|
@ -67,6 +67,11 @@
|
|||
#
|
||||
# (module-path "${gimp_dir}/modules:${gimp_plug_in_dir}/modules")
|
||||
|
||||
# Sets the interpreter search path. This is a colon-separated list of
|
||||
# folders to search.
|
||||
#
|
||||
# (interpreter-path "${gimp_dir}/interpreters:${gimp_plug_in_dir}/interpreters")
|
||||
|
||||
# Sets the environ search path. This is a colon-separated list of folders to
|
||||
# search.
|
||||
#
|
||||
|
@ -170,8 +175,8 @@
|
|||
# Sets the default image in the "File/New" dialog. This is a parameter list.
|
||||
#
|
||||
# (default-image
|
||||
# (width 420)
|
||||
# (height 300)
|
||||
# (width 377)
|
||||
# (height 233)
|
||||
# (unit pixels)
|
||||
# (xresolution 72.000000)
|
||||
# (yresolution 72.000000)
|
||||
|
@ -186,8 +191,8 @@
|
|||
# (style intersections)
|
||||
# (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000))
|
||||
# (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000))
|
||||
# (xspacing 10.000000)
|
||||
# (yspacing 10.000000)
|
||||
# (xspacing 32.000000)
|
||||
# (yspacing 32.000000)
|
||||
# (spacing-unit inches)
|
||||
# (xoffset 0.000000)
|
||||
# (yoffset 0.000000)
|
||||
|
@ -254,6 +259,13 @@
|
|||
#
|
||||
# (min-colors 144)
|
||||
|
||||
# Defines the color management behavior. This is a parameter list.
|
||||
#
|
||||
# (color-management
|
||||
# (mode display)
|
||||
# (display-rendering-intent perceptual)
|
||||
# (simulation-rendering-intent perceptual))
|
||||
|
||||
# Sets the size of the checkerboard used to display transparency. Possible
|
||||
# values are small-checks, medium-checks and large-checks.
|
||||
#
|
||||
|
|
|
@ -11,10 +11,11 @@ PREFS_IMAGES = \
|
|||
environment.png \
|
||||
folders.png \
|
||||
folders-brushes.png \
|
||||
folders-environ.png \
|
||||
folders-fonts.png \
|
||||
folders-gradients.png \
|
||||
folders-interp.png \
|
||||
folders-modules.png \
|
||||
folders-environ.png \
|
||||
folders-palettes.png \
|
||||
folders-patterns.png \
|
||||
folders-plug-ins.png \
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
Loading…
Reference in New Issue