1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpplugin.c
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "config.h"
21 
22 #ifndef _WIN32
23 #define _GNU_SOURCE
24 #endif
25 
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 
35 #ifdef HAVE_SYS_WAIT_H
36 #include <sys/wait.h>
37 #endif
38 
39 #ifdef HAVE_SYS_PARAM_H
40 #include <sys/param.h>
41 #endif
42 
43 #include <gdk-pixbuf/gdk-pixbuf.h>
44 #include <gegl.h>
45 
46 #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
47 
48 #define STRICT
49 #include <windows.h>
50 #include <process.h>
51 
52 #ifdef G_OS_WIN32
53 #include <fcntl.h>
54 #include <io.h>
55 
56 #ifndef pipe
57 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
58 #endif
59 
60 #endif
61 
62 #ifdef G_WITH_CYGWIN
63 #define O_TEXT    0x0100  /* text file   */
64 #define _O_TEXT   0x0100  /* text file   */
65 #define O_BINARY  0x0200  /* binary file */
66 #define _O_BINARY 0x0200  /* binary file */
67 #endif
68 
69 #endif /* G_OS_WIN32 || G_WITH_CYGWIN */
70 
71 #include "libgimpbase/gimpbase.h"
72 #include "libgimpbase/gimpprotocol.h"
73 #include "libgimpbase/gimpwire.h"
74 
75 #include "plug-in-types.h"
76 
77 #include "core/gimp.h"
78 #include "core/gimp-spawn.h"
79 #include "core/gimpprogress.h"
80 
81 #include "pdb/gimppdbcontext.h"
82 
83 #include "gimpenvirontable.h"
84 #include "gimpinterpreterdb.h"
85 #include "gimpplugin.h"
86 #include "gimpplugin-message.h"
87 #include "gimpplugin-progress.h"
88 #include "gimpplugindebug.h"
89 #include "gimpplugindef.h"
90 #include "gimppluginmanager.h"
91 #include "gimppluginmanager-help-domain.h"
92 #include "gimppluginmanager-locale-domain.h"
93 #include "gimptemporaryprocedure.h"
94 #include "plug-in-params.h"
95 
96 #include "gimp-intl.h"
97 
98 
99 static void       gimp_plug_in_finalize      (GObject      *object);
100 
101 static gboolean   gimp_plug_in_recv_message  (GIOChannel   *channel,
102                                               GIOCondition  cond,
103                                               gpointer      data);
104 static gboolean   gimp_plug_in_write         (GIOChannel   *channel,
105                                               const guint8 *buf,
106                                               gulong        count,
107                                               gpointer      data);
108 static gboolean   gimp_plug_in_flush         (GIOChannel   *channel,
109                                               gpointer      data);
110 
111 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
112 static void       gimp_plug_in_set_dll_directory (const gchar *path);
113 #endif
114 
115 
116 
G_DEFINE_TYPE(GimpPlugIn,gimp_plug_in,GIMP_TYPE_OBJECT)117 G_DEFINE_TYPE (GimpPlugIn, gimp_plug_in, GIMP_TYPE_OBJECT)
118 
119 #define parent_class gimp_plug_in_parent_class
120 
121 
122 static void
123 gimp_plug_in_class_init (GimpPlugInClass *klass)
124 {
125   GObjectClass *object_class = G_OBJECT_CLASS (klass);
126 
127   object_class->finalize = gimp_plug_in_finalize;
128 
129   /* initialize the gimp protocol library and set the read and
130    *  write handlers.
131    */
132   gp_init ();
133   gimp_wire_set_writer (gimp_plug_in_write);
134   gimp_wire_set_flusher (gimp_plug_in_flush);
135 }
136 
137 static void
gimp_plug_in_init(GimpPlugIn * plug_in)138 gimp_plug_in_init (GimpPlugIn *plug_in)
139 {
140   plug_in->manager            = NULL;
141   plug_in->file               = NULL;
142 
143   plug_in->call_mode          = GIMP_PLUG_IN_CALL_NONE;
144   plug_in->open               = FALSE;
145   plug_in->hup                = FALSE;
146   plug_in->pid                = 0;
147 
148   plug_in->my_read            = NULL;
149   plug_in->my_write           = NULL;
150   plug_in->his_read           = NULL;
151   plug_in->his_write          = NULL;
152 
153   plug_in->input_id           = 0;
154   plug_in->write_buffer_index = 0;
155 
156   plug_in->temp_procedures    = NULL;
157 
158   plug_in->ext_main_loop      = NULL;
159 
160   plug_in->temp_proc_frames   = NULL;
161 
162   plug_in->plug_in_def        = NULL;
163 }
164 
165 static void
gimp_plug_in_finalize(GObject * object)166 gimp_plug_in_finalize (GObject *object)
167 {
168   GimpPlugIn *plug_in = GIMP_PLUG_IN (object);
169 
170   g_clear_object (&plug_in->file);
171 
172   gimp_plug_in_proc_frame_dispose (&plug_in->main_proc_frame, plug_in);
173 
174   G_OBJECT_CLASS (parent_class)->finalize (object);
175 }
176 
177 static gboolean
gimp_plug_in_recv_message(GIOChannel * channel,GIOCondition cond,gpointer data)178 gimp_plug_in_recv_message (GIOChannel   *channel,
179                            GIOCondition  cond,
180                            gpointer      data)
181 {
182   GimpPlugIn *plug_in     = data;
183   gboolean    got_message = FALSE;
184 
185 #ifdef G_OS_WIN32
186   /* Workaround for GLib bug #137968: sometimes we are called for no
187    * reason...
188    */
189   if (cond == 0)
190     return TRUE;
191 #endif
192 
193   if (plug_in->my_read == NULL)
194     return TRUE;
195 
196   g_object_ref (plug_in);
197 
198   if (cond & (G_IO_IN | G_IO_PRI))
199     {
200       GimpWireMessage msg;
201 
202       memset (&msg, 0, sizeof (GimpWireMessage));
203 
204       if (! gimp_wire_read_msg (plug_in->my_read, &msg, plug_in))
205         {
206           gimp_plug_in_close (plug_in, TRUE);
207         }
208       else
209         {
210           gimp_plug_in_handle_message (plug_in, &msg);
211           gimp_wire_destroy (&msg);
212           got_message = TRUE;
213         }
214     }
215 
216   if (cond & (G_IO_ERR | G_IO_HUP))
217     {
218       if (cond & G_IO_HUP)
219         plug_in->hup = TRUE;
220 
221       if (plug_in->open)
222         gimp_plug_in_close (plug_in, TRUE);
223     }
224 
225   if (! got_message)
226     {
227       GimpPlugInProcFrame *frame    = gimp_plug_in_get_proc_frame (plug_in);
228       GimpProgress        *progress = frame ? frame->progress : NULL;
229 
230       gimp_message (plug_in->manager->gimp, G_OBJECT (progress),
231                     GIMP_MESSAGE_ERROR,
232                     _("Plug-in crashed: \"%s\"\n(%s)\n\n"
233                       "The dying plug-in may have messed up GIMP's internal "
234                       "state. You may want to save your images and restart "
235                       "GIMP to be on the safe side."),
236                     gimp_object_get_name (plug_in),
237                     gimp_file_get_utf8_name (plug_in->file));
238     }
239 
240   g_object_unref (plug_in);
241 
242   return TRUE;
243 }
244 
245 static gboolean
gimp_plug_in_write(GIOChannel * channel,const guint8 * buf,gulong count,gpointer data)246 gimp_plug_in_write (GIOChannel   *channel,
247                     const guint8 *buf,
248                     gulong        count,
249                     gpointer      data)
250 {
251   GimpPlugIn *plug_in = data;
252   gulong      bytes;
253 
254   while (count > 0)
255     {
256       if ((plug_in->write_buffer_index + count) >= WRITE_BUFFER_SIZE)
257         {
258           bytes = WRITE_BUFFER_SIZE - plug_in->write_buffer_index;
259           memcpy (&plug_in->write_buffer[plug_in->write_buffer_index],
260                   buf, bytes);
261           plug_in->write_buffer_index += bytes;
262           if (! gimp_wire_flush (channel, plug_in))
263             return FALSE;
264         }
265       else
266         {
267           bytes = count;
268           memcpy (&plug_in->write_buffer[plug_in->write_buffer_index],
269                   buf, bytes);
270           plug_in->write_buffer_index += bytes;
271         }
272 
273       buf += bytes;
274       count -= bytes;
275     }
276 
277   return TRUE;
278 }
279 
280 static gboolean
gimp_plug_in_flush(GIOChannel * channel,gpointer data)281 gimp_plug_in_flush (GIOChannel *channel,
282                     gpointer    data)
283 {
284   GimpPlugIn *plug_in = data;
285 
286   if (plug_in->write_buffer_index > 0)
287     {
288       GIOStatus  status;
289       GError    *error = NULL;
290       gint       count;
291       gsize      bytes;
292 
293       count = 0;
294       while (count != plug_in->write_buffer_index)
295         {
296           do
297             {
298               bytes = 0;
299               status = g_io_channel_write_chars (channel,
300                                                  &plug_in->write_buffer[count],
301                                                  (plug_in->write_buffer_index - count),
302                                                  &bytes,
303                                                  &error);
304             }
305           while (status == G_IO_STATUS_AGAIN);
306 
307           if (status != G_IO_STATUS_NORMAL)
308             {
309               if (error)
310                 {
311                   g_warning ("%s: plug_in_flush(): error: %s",
312                              gimp_filename_to_utf8 (g_get_prgname ()),
313                              error->message);
314                   g_error_free (error);
315                 }
316               else
317                 {
318                   g_warning ("%s: plug_in_flush(): error",
319                              gimp_filename_to_utf8 (g_get_prgname ()));
320                 }
321 
322               return FALSE;
323             }
324 
325           count += bytes;
326         }
327 
328       plug_in->write_buffer_index = 0;
329     }
330 
331   return TRUE;
332 }
333 
334 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
335 static void
gimp_plug_in_set_dll_directory(const gchar * path)336 gimp_plug_in_set_dll_directory (const gchar *path)
337 {
338   const gchar *install_dir;
339   gchar       *bin_dir;
340   LPWSTR       w_bin_dir;
341   DWORD        BinaryType;
342   int          n;
343 
344   w_bin_dir = NULL;
345   install_dir = gimp_installation_directory ();
346   if (path                               &&
347       GetBinaryTypeA (path, &BinaryType) &&
348       BinaryType == SCS_32BIT_BINARY)
349     bin_dir = g_build_filename (install_dir, WIN32_32BIT_DLL_FOLDER, NULL);
350   else
351     bin_dir = g_build_filename (install_dir, "bin", NULL);
352 
353   n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
354                            bin_dir, -1, NULL, 0);
355   if (n == 0)
356     goto out;
357 
358   w_bin_dir = g_malloc_n (n + 1, sizeof (wchar_t));
359   n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
360                            bin_dir, -1,
361                            w_bin_dir, (n + 1) * sizeof (wchar_t));
362   if (n == 0)
363     goto out;
364 
365   SetDllDirectoryW (w_bin_dir);
366 
367 out:
368   if (w_bin_dir)
369     g_free ((void*) w_bin_dir);
370   g_free (bin_dir);
371 }
372 #endif
373 
374 
375 /*  public functions  */
376 
377 GimpPlugIn *
gimp_plug_in_new(GimpPlugInManager * manager,GimpContext * context,GimpProgress * progress,GimpPlugInProcedure * procedure,GFile * file)378 gimp_plug_in_new (GimpPlugInManager   *manager,
379                   GimpContext         *context,
380                   GimpProgress        *progress,
381                   GimpPlugInProcedure *procedure,
382                   GFile               *file)
383 {
384   GimpPlugIn *plug_in;
385 
386   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
387   g_return_val_if_fail (GIMP_IS_PDB_CONTEXT (context), NULL);
388   g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
389   g_return_val_if_fail (procedure == NULL ||
390                         GIMP_IS_PLUG_IN_PROCEDURE (procedure), NULL);
391   g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
392   g_return_val_if_fail ((procedure != NULL || file != NULL) &&
393                         ! (procedure != NULL && file != NULL), NULL);
394 
395   plug_in = g_object_new (GIMP_TYPE_PLUG_IN, NULL);
396 
397   if (! file)
398     file = gimp_plug_in_procedure_get_file (procedure);
399 
400   gimp_object_take_name (GIMP_OBJECT (plug_in),
401                          g_path_get_basename (gimp_file_get_utf8_name (file)));
402 
403   plug_in->manager = manager;
404   plug_in->file    = g_object_ref (file);
405 
406   gimp_plug_in_proc_frame_init (&plug_in->main_proc_frame,
407                                 context, progress, procedure);
408 
409   return plug_in;
410 }
411 
412 gboolean
gimp_plug_in_open(GimpPlugIn * plug_in,GimpPlugInCallMode call_mode,gboolean synchronous)413 gimp_plug_in_open (GimpPlugIn         *plug_in,
414                    GimpPlugInCallMode  call_mode,
415                    gboolean            synchronous)
416 {
417   gchar        *progname;
418   gint          my_read[2];
419   gint          my_write[2];
420   gchar       **envp;
421   const gchar  *args[9];
422   gchar       **argv;
423   gint          argc;
424   gchar        *interp, *interp_arg;
425   gchar        *his_read_fd, *his_write_fd;
426   const gchar  *mode;
427   gchar        *stm;
428   GError       *error = NULL;
429   gboolean      debug;
430   guint         debug_flag;
431   guint         spawn_flags;
432 
433   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
434   g_return_val_if_fail (plug_in->call_mode == GIMP_PLUG_IN_CALL_NONE, FALSE);
435 
436   /* Open two pipes. (Bidirectional communication).
437    */
438   if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
439     {
440       gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
441                     "Unable to run plug-in \"%s\"\n(%s)\n\npipe() failed: %s",
442                     gimp_object_get_name (plug_in),
443                     gimp_file_get_utf8_name (plug_in->file),
444                     g_strerror (errno));
445       return FALSE;
446     }
447 
448 #if defined(G_WITH_CYGWIN)
449   /* Set to binary mode */
450   setmode (my_read[0], _O_BINARY);
451   setmode (my_write[0], _O_BINARY);
452   setmode (my_read[1], _O_BINARY);
453   setmode (my_write[1], _O_BINARY);
454 #endif
455 
456   /* Prevent the plug-in from inheriting our end of the pipes */
457   gimp_spawn_set_cloexec (my_read[0]);
458   gimp_spawn_set_cloexec (my_write[1]);
459 
460 #ifdef G_OS_WIN32
461   plug_in->my_read   = g_io_channel_win32_new_fd (my_read[0]);
462   plug_in->my_write  = g_io_channel_win32_new_fd (my_write[1]);
463   plug_in->his_read  = g_io_channel_win32_new_fd (my_write[0]);
464   plug_in->his_write = g_io_channel_win32_new_fd (my_read[1]);
465 #else
466   plug_in->my_read   = g_io_channel_unix_new (my_read[0]);
467   plug_in->my_write  = g_io_channel_unix_new (my_write[1]);
468   plug_in->his_read  = g_io_channel_unix_new (my_write[0]);
469   plug_in->his_write = g_io_channel_unix_new (my_read[1]);
470 #endif
471 
472   g_io_channel_set_encoding (plug_in->my_read, NULL, NULL);
473   g_io_channel_set_encoding (plug_in->my_write, NULL, NULL);
474   g_io_channel_set_encoding (plug_in->his_read, NULL, NULL);
475   g_io_channel_set_encoding (plug_in->his_write, NULL, NULL);
476 
477   g_io_channel_set_buffered (plug_in->my_read, FALSE);
478   g_io_channel_set_buffered (plug_in->my_write, FALSE);
479   g_io_channel_set_buffered (plug_in->his_read, FALSE);
480   g_io_channel_set_buffered (plug_in->his_write, FALSE);
481 
482   g_io_channel_set_close_on_unref (plug_in->my_read, TRUE);
483   g_io_channel_set_close_on_unref (plug_in->my_write, TRUE);
484   g_io_channel_set_close_on_unref (plug_in->his_read, TRUE);
485   g_io_channel_set_close_on_unref (plug_in->his_write, TRUE);
486 
487   /* Remember the file descriptors for the pipes.
488    */
489   his_read_fd  = g_strdup_printf ("%d",
490                                   g_io_channel_unix_get_fd (plug_in->his_read));
491   his_write_fd = g_strdup_printf ("%d",
492                                   g_io_channel_unix_get_fd (plug_in->his_write));
493 
494   switch (call_mode)
495     {
496     case GIMP_PLUG_IN_CALL_QUERY:
497       mode = "-query";
498       debug_flag = GIMP_DEBUG_WRAP_QUERY;
499       break;
500 
501     case GIMP_PLUG_IN_CALL_INIT:
502       mode = "-init";
503       debug_flag = GIMP_DEBUG_WRAP_INIT;
504       break;
505 
506     case GIMP_PLUG_IN_CALL_RUN:
507       mode = "-run";
508       debug_flag = GIMP_DEBUG_WRAP_RUN;
509       break;
510 
511     default:
512       gimp_assert_not_reached ();
513     }
514 
515   stm = g_strdup_printf ("%d", plug_in->manager->gimp->stack_trace_mode);
516 
517   progname = g_file_get_path (plug_in->file);
518 
519   interp = gimp_interpreter_db_resolve (plug_in->manager->interpreter_db,
520                                         progname, &interp_arg);
521 
522   argc = 0;
523 
524   if (interp)
525     args[argc++] = interp;
526 
527   if (interp_arg)
528     args[argc++] = interp_arg;
529 
530   args[argc++] = progname;
531   args[argc++] = "-gimp";
532   args[argc++] = his_read_fd;
533   args[argc++] = his_write_fd;
534   args[argc++] = mode;
535   args[argc++] = stm;
536   args[argc++] = NULL;
537 
538   argv = (gchar **) args;
539   envp = gimp_environ_table_get_envp (plug_in->manager->environ_table);
540   spawn_flags = (G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
541                  G_SPAWN_DO_NOT_REAP_CHILD      |
542                  G_SPAWN_CHILD_INHERITS_STDIN);
543 
544   debug = FALSE;
545 
546   if (plug_in->manager->debug)
547     {
548       gchar **debug_argv = gimp_plug_in_debug_argv (plug_in->manager->debug,
549                                                     progname,
550                                                     debug_flag, args);
551 
552       if (debug_argv)
553         {
554           debug = TRUE;
555           argv = debug_argv;
556           spawn_flags |= G_SPAWN_SEARCH_PATH;
557         }
558     }
559 
560   /* Fork another process. We'll remember the process id so that we
561    * can later use it to kill the filter if necessary.
562    */
563 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
564   gimp_plug_in_set_dll_directory (argv[0]);
565 #endif
566   if (! gimp_spawn_async (argv, envp, spawn_flags, &plug_in->pid, &error))
567     {
568       gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
569                     "Unable to run plug-in \"%s\"\n(%s)\n\n%s",
570                     gimp_object_get_name (plug_in),
571                     gimp_file_get_utf8_name (plug_in->file),
572                     error->message);
573       g_clear_error (&error);
574       goto cleanup;
575     }
576 
577   g_clear_pointer (&plug_in->his_read,  g_io_channel_unref);
578   g_clear_pointer (&plug_in->his_write, g_io_channel_unref);
579 
580   if (! synchronous)
581     {
582       GSource *source;
583 
584       source = g_io_create_watch (plug_in->my_read,
585                                   G_IO_IN  | G_IO_PRI | G_IO_ERR | G_IO_HUP);
586 
587       g_source_set_callback (source,
588                              (GSourceFunc) gimp_plug_in_recv_message, plug_in,
589                              NULL);
590 
591       g_source_set_can_recurse (source, TRUE);
592 
593       plug_in->input_id = g_source_attach (source, NULL);
594       g_source_unref (source);
595     }
596 
597   plug_in->open      = TRUE;
598   plug_in->call_mode = call_mode;
599 
600   gimp_plug_in_manager_add_open_plug_in (plug_in->manager, plug_in);
601 
602  cleanup:
603 
604 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
605   gimp_plug_in_set_dll_directory (NULL);
606 #endif
607 
608   if (debug)
609     g_free (argv);
610 
611   g_free (his_read_fd);
612   g_free (his_write_fd);
613   g_free (stm);
614   g_free (interp);
615   g_free (interp_arg);
616   g_free (progname);
617 
618   return plug_in->open;
619 }
620 
621 void
gimp_plug_in_close(GimpPlugIn * plug_in,gboolean kill_it)622 gimp_plug_in_close (GimpPlugIn *plug_in,
623                     gboolean    kill_it)
624 {
625   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
626   g_return_if_fail (plug_in->open);
627 
628   plug_in->open = FALSE;
629 
630   if (plug_in->pid)
631     {
632 #ifndef G_OS_WIN32
633       gint status;
634 #endif
635 
636       /*  Ask the filter to exit gracefully,
637           but not if it is closed because of a broken pipe.  */
638       if (kill_it && ! plug_in->hup)
639         {
640           gp_quit_write (plug_in->my_write, plug_in);
641 
642           /*  give the plug-in some time (10 ms)  */
643           g_usleep (10000);
644         }
645 
646       /* If necessary, kill the filter. */
647 
648 #ifndef G_OS_WIN32
649 
650       if (kill_it)
651         {
652           if (plug_in->manager->gimp->be_verbose)
653             g_print ("Terminating plug-in: '%s'\n",
654                      gimp_file_get_utf8_name (plug_in->file));
655 
656           /*  If the plug-in opened a process group, kill the group instead
657            *  of only the plug-in, so we kill the plug-in's children too
658            */
659           if (getpgid (0) != getpgid (plug_in->pid))
660             status = kill (- plug_in->pid, SIGKILL);
661           else
662             status = kill (plug_in->pid, SIGKILL);
663         }
664 
665       /* Wait for the process to exit. This will happen
666        * immediately if it was just killed.
667        */
668       waitpid (plug_in->pid, &status, 0);
669 
670 #else /* G_OS_WIN32 */
671 
672       if (kill_it)
673         {
674           /* Trying to avoid TerminateProcess (does mostly work).
675            * Otherwise some of our needed DLLs may get into an
676            * unstable state (see Win32 API docs).
677            */
678           DWORD dwExitCode = STILL_ACTIVE;
679           DWORD dwTries    = 10;
680 
681           while (dwExitCode == STILL_ACTIVE &&
682                  GetExitCodeProcess ((HANDLE) plug_in->pid, &dwExitCode) &&
683                  (dwTries > 0))
684             {
685               Sleep (10);
686               dwTries--;
687             }
688 
689           if (dwExitCode == STILL_ACTIVE)
690             {
691               if (plug_in->manager->gimp->be_verbose)
692                 g_print ("Terminating plug-in: '%s'\n",
693                          gimp_file_get_utf8_name (plug_in->file));
694 
695               TerminateProcess ((HANDLE) plug_in->pid, 0);
696             }
697         }
698 
699 #endif /* G_OS_WIN32 */
700 
701       g_spawn_close_pid (plug_in->pid);
702       plug_in->pid = 0;
703     }
704 
705   /* Remove the input handler. */
706   if (plug_in->input_id)
707     {
708       g_source_remove (plug_in->input_id);
709       plug_in->input_id = 0;
710     }
711 
712   /* Close the pipes. */
713   g_clear_pointer (&plug_in->my_read,   g_io_channel_unref);
714   g_clear_pointer (&plug_in->my_write,  g_io_channel_unref);
715   g_clear_pointer (&plug_in->his_read,  g_io_channel_unref);
716   g_clear_pointer (&plug_in->his_write, g_io_channel_unref);
717 
718   gimp_wire_clear_error ();
719 
720   while (plug_in->temp_proc_frames)
721     {
722       GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
723 
724 #ifdef GIMP_UNSTABLE
725       g_printerr ("plug-in '%s' aborted before sending its "
726                   "temporary procedure return values\n",
727                   gimp_object_get_name (plug_in));
728 #endif
729 
730       if (proc_frame->main_loop &&
731           g_main_loop_is_running (proc_frame->main_loop))
732         {
733           g_main_loop_quit (proc_frame->main_loop);
734         }
735 
736       /* pop the frame here, because normally this only happens in
737        * gimp_plug_in_handle_temp_proc_return(), which can't
738        * be called after plug_in_close()
739        */
740       gimp_plug_in_proc_frame_pop (plug_in);
741     }
742 
743   if (plug_in->main_proc_frame.main_loop &&
744       g_main_loop_is_running (plug_in->main_proc_frame.main_loop))
745     {
746 #ifdef GIMP_UNSTABLE
747       g_printerr ("plug-in '%s' aborted before sending its "
748                   "procedure return values\n",
749                   gimp_object_get_name (plug_in));
750 #endif
751 
752       g_main_loop_quit (plug_in->main_proc_frame.main_loop);
753     }
754 
755   if (plug_in->ext_main_loop &&
756       g_main_loop_is_running (plug_in->ext_main_loop))
757     {
758 #ifdef GIMP_UNSTABLE
759       g_printerr ("extension '%s' aborted before sending its "
760                   "extension_ack message\n",
761                   gimp_object_get_name (plug_in));
762 #endif
763 
764       g_main_loop_quit (plug_in->ext_main_loop);
765     }
766 
767   /* Unregister any temporary procedures. */
768   while (plug_in->temp_procedures)
769     gimp_plug_in_remove_temp_proc (plug_in, plug_in->temp_procedures->data);
770 
771   gimp_plug_in_manager_remove_open_plug_in (plug_in->manager, plug_in);
772 }
773 
774 GimpPlugInProcFrame *
gimp_plug_in_get_proc_frame(GimpPlugIn * plug_in)775 gimp_plug_in_get_proc_frame (GimpPlugIn *plug_in)
776 {
777   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
778 
779   if (plug_in->temp_proc_frames)
780     return plug_in->temp_proc_frames->data;
781   else
782     return &plug_in->main_proc_frame;
783 }
784 
785 GimpPlugInProcFrame *
gimp_plug_in_proc_frame_push(GimpPlugIn * plug_in,GimpContext * context,GimpProgress * progress,GimpTemporaryProcedure * procedure)786 gimp_plug_in_proc_frame_push (GimpPlugIn             *plug_in,
787                               GimpContext            *context,
788                               GimpProgress           *progress,
789                               GimpTemporaryProcedure *procedure)
790 {
791   GimpPlugInProcFrame *proc_frame;
792 
793   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
794   g_return_val_if_fail (GIMP_IS_PDB_CONTEXT (context), NULL);
795   g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
796   g_return_val_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (procedure), NULL);
797 
798   proc_frame = gimp_plug_in_proc_frame_new (context, progress,
799                                             GIMP_PLUG_IN_PROCEDURE (procedure));
800 
801   plug_in->temp_proc_frames = g_list_prepend (plug_in->temp_proc_frames,
802                                               proc_frame);
803 
804   return proc_frame;
805 }
806 
807 void
gimp_plug_in_proc_frame_pop(GimpPlugIn * plug_in)808 gimp_plug_in_proc_frame_pop (GimpPlugIn *plug_in)
809 {
810   GimpPlugInProcFrame *proc_frame;
811 
812   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
813   g_return_if_fail (plug_in->temp_proc_frames != NULL);
814 
815   proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data;
816 
817   gimp_plug_in_proc_frame_unref (proc_frame, plug_in);
818 
819   plug_in->temp_proc_frames = g_list_remove (plug_in->temp_proc_frames,
820                                              proc_frame);
821 }
822 
823 void
gimp_plug_in_main_loop(GimpPlugIn * plug_in)824 gimp_plug_in_main_loop (GimpPlugIn *plug_in)
825 {
826   GimpPlugInProcFrame *proc_frame;
827 
828   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
829   g_return_if_fail (plug_in->temp_proc_frames != NULL);
830 
831   proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data;
832 
833   g_return_if_fail (proc_frame->main_loop == NULL);
834 
835   proc_frame->main_loop = g_main_loop_new (NULL, FALSE);
836 
837   gimp_threads_leave (plug_in->manager->gimp);
838   g_main_loop_run (proc_frame->main_loop);
839   gimp_threads_enter (plug_in->manager->gimp);
840 
841   g_clear_pointer (&proc_frame->main_loop, g_main_loop_unref);
842 }
843 
844 void
gimp_plug_in_main_loop_quit(GimpPlugIn * plug_in)845 gimp_plug_in_main_loop_quit (GimpPlugIn *plug_in)
846 {
847   GimpPlugInProcFrame *proc_frame;
848 
849   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
850   g_return_if_fail (plug_in->temp_proc_frames != NULL);
851 
852   proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data;
853 
854   g_return_if_fail (proc_frame->main_loop != NULL);
855 
856   g_main_loop_quit (proc_frame->main_loop);
857 }
858 
859 const gchar *
gimp_plug_in_get_undo_desc(GimpPlugIn * plug_in)860 gimp_plug_in_get_undo_desc (GimpPlugIn *plug_in)
861 {
862   GimpPlugInProcFrame *proc_frame;
863   const gchar         *undo_desc = NULL;
864 
865   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
866 
867   proc_frame = gimp_plug_in_get_proc_frame (plug_in);
868 
869   if (proc_frame && proc_frame->procedure)
870     undo_desc = gimp_procedure_get_label (proc_frame->procedure);
871 
872   return undo_desc ? undo_desc : gimp_object_get_name (plug_in);
873 }
874 
875 /*  called from the PDB (gimp_plugin_menu_register)  */
876 gboolean
gimp_plug_in_menu_register(GimpPlugIn * plug_in,const gchar * proc_name,const gchar * menu_path)877 gimp_plug_in_menu_register (GimpPlugIn  *plug_in,
878                             const gchar *proc_name,
879                             const gchar *menu_path)
880 {
881   GimpPlugInProcedure *proc  = NULL;
882   GError              *error = NULL;
883 
884   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
885   g_return_val_if_fail (proc_name != NULL, FALSE);
886   g_return_val_if_fail (menu_path != NULL, FALSE);
887 
888   if (plug_in->plug_in_def)
889     proc = gimp_plug_in_procedure_find (plug_in->plug_in_def->procedures,
890                                         proc_name);
891 
892   if (! proc)
893     proc = gimp_plug_in_procedure_find (plug_in->temp_procedures, proc_name);
894 
895   if (! proc)
896     {
897       gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
898                     "Plug-in \"%s\"\n(%s)\n"
899                     "attempted to register the menu item \"%s\" "
900                     "for the procedure \"%s\".\n"
901                     "It has however not installed that procedure.  This "
902                     "is not allowed.",
903                     gimp_object_get_name (plug_in),
904                     gimp_file_get_utf8_name (plug_in->file),
905                     menu_path, proc_name);
906 
907       return FALSE;
908     }
909 
910   switch (GIMP_PROCEDURE (proc)->proc_type)
911     {
912     case GIMP_INTERNAL:
913       return FALSE;
914 
915     case GIMP_PLUGIN:
916     case GIMP_EXTENSION:
917       if (plug_in->call_mode != GIMP_PLUG_IN_CALL_QUERY &&
918           plug_in->call_mode != GIMP_PLUG_IN_CALL_INIT)
919         return FALSE;
920 
921     case GIMP_TEMPORARY:
922       break;
923     }
924 
925   if (! proc->menu_label)
926     {
927       gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
928                     "Plug-in \"%s\"\n(%s)\n"
929                     "attempted to register the menu item \"%s\" "
930                     "for procedure \"%s\".\n"
931                     "The menu label given in gimp_install_procedure() "
932                     "already contained a path.  To make this work, "
933                     "pass just the menu's label to "
934                     "gimp_install_procedure().",
935                     gimp_object_get_name (plug_in),
936                     gimp_file_get_utf8_name (plug_in->file),
937                     menu_path, proc_name);
938 
939       return FALSE;
940     }
941 
942   if (! strlen (proc->menu_label))
943     {
944       gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
945                     "Plug-in \"%s\"\n(%s)\n"
946                     "attempted to register the procedure \"%s\" "
947                     "in the menu \"%s\", but the procedure has no label.  "
948                     "This is not allowed.",
949                     gimp_object_get_name (plug_in),
950                     gimp_file_get_utf8_name (plug_in->file),
951                     proc_name, menu_path);
952 
953       return FALSE;
954     }
955 
956   if (! gimp_plug_in_procedure_add_menu_path (proc, menu_path, &error))
957     {
958       gimp_message_literal (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
959                             error->message);
960       g_clear_error (&error);
961 
962       return FALSE;
963     }
964 
965   return TRUE;
966 }
967 
968 void
gimp_plug_in_add_temp_proc(GimpPlugIn * plug_in,GimpTemporaryProcedure * proc)969 gimp_plug_in_add_temp_proc (GimpPlugIn             *plug_in,
970                             GimpTemporaryProcedure *proc)
971 {
972   GimpPlugInProcedure *overridden;
973   const gchar         *locale_domain;
974   const gchar         *help_domain;
975 
976   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
977   g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (proc));
978 
979   overridden = gimp_plug_in_procedure_find (plug_in->temp_procedures,
980                                             gimp_object_get_name (proc));
981 
982   if (overridden)
983     gimp_plug_in_remove_temp_proc (plug_in,
984                                    GIMP_TEMPORARY_PROCEDURE (overridden));
985 
986   locale_domain = gimp_plug_in_manager_get_locale_domain (plug_in->manager,
987                                                           plug_in->file,
988                                                           NULL);
989   help_domain = gimp_plug_in_manager_get_help_domain (plug_in->manager,
990                                                       plug_in->file,
991                                                       NULL);
992 
993   gimp_plug_in_procedure_set_locale_domain (GIMP_PLUG_IN_PROCEDURE (proc),
994                                             locale_domain);
995   gimp_plug_in_procedure_set_help_domain (GIMP_PLUG_IN_PROCEDURE (proc),
996                                           help_domain);
997 
998   plug_in->temp_procedures = g_slist_prepend (plug_in->temp_procedures,
999                                               g_object_ref (proc));
1000   gimp_plug_in_manager_add_temp_proc (plug_in->manager, proc);
1001 }
1002 
1003 void
gimp_plug_in_remove_temp_proc(GimpPlugIn * plug_in,GimpTemporaryProcedure * proc)1004 gimp_plug_in_remove_temp_proc (GimpPlugIn             *plug_in,
1005                                GimpTemporaryProcedure *proc)
1006 {
1007   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
1008   g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (proc));
1009 
1010   plug_in->temp_procedures = g_slist_remove (plug_in->temp_procedures, proc);
1011 
1012   gimp_plug_in_manager_remove_temp_proc (plug_in->manager, proc);
1013   g_object_unref (proc);
1014 }
1015 
1016 void
gimp_plug_in_set_error_handler(GimpPlugIn * plug_in,GimpPDBErrorHandler handler)1017 gimp_plug_in_set_error_handler (GimpPlugIn          *plug_in,
1018                                 GimpPDBErrorHandler  handler)
1019 {
1020   GimpPlugInProcFrame *proc_frame;
1021 
1022   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
1023 
1024   proc_frame = gimp_plug_in_get_proc_frame (plug_in);
1025 
1026   if (proc_frame)
1027     proc_frame->error_handler = handler;
1028 }
1029 
1030 GimpPDBErrorHandler
gimp_plug_in_get_error_handler(GimpPlugIn * plug_in)1031 gimp_plug_in_get_error_handler (GimpPlugIn *plug_in)
1032 {
1033   GimpPlugInProcFrame *proc_frame;
1034 
1035   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in),
1036                         GIMP_PDB_ERROR_HANDLER_INTERNAL);
1037 
1038   proc_frame = gimp_plug_in_get_proc_frame (plug_in);
1039 
1040   if (proc_frame)
1041     return proc_frame->error_handler;
1042 
1043   return GIMP_PDB_ERROR_HANDLER_INTERNAL;
1044 }
1045 
1046 void
gimp_plug_in_enable_precision(GimpPlugIn * plug_in)1047 gimp_plug_in_enable_precision (GimpPlugIn *plug_in)
1048 {
1049   g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
1050 
1051   plug_in->precision = TRUE;
1052 }
1053 
1054 gboolean
gimp_plug_in_precision_enabled(GimpPlugIn * plug_in)1055 gimp_plug_in_precision_enabled (GimpPlugIn *plug_in)
1056 {
1057   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
1058 
1059   return plug_in->precision;
1060 }
1061