This source file includes following definitions.
- exec_cleanup_script
- exec_cleanup_file_name
- exec_get_file_name
- exec_expand_format
- exec_get_export_variables
- exec_make_shell_string
- exec_extension_view
- exec_extension_cd
- exec_extension
- get_popen_information
- get_file_type_local
- get_file_encoding_local
- regex_check_type
- check_old_extension_file
- load_extension_file
- flush_extension_file
- regex_command_for
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include <config.h>
33
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 #include "lib/global.h"
41 #include "lib/tty/tty.h"
42 #include "lib/search.h"
43 #include "lib/fileloc.h"
44 #include "lib/mcconfig.h"
45 #include "lib/util.h"
46 #include "lib/vfs/vfs.h"
47 #include "lib/widget.h"
48 #include "lib/charsets.h"
49
50 #ifdef USE_FILE_CMD
51 #include "src/setup.h"
52 #endif
53 #include "src/execute.h"
54 #include "src/history.h"
55 #include "src/usermenu.h"
56
57 #include "src/consaver/cons.saver.h"
58 #include "src/viewer/mcviewer.h"
59 #include "src/selcodepage.h"
60 #include "src/util.h"
61
62 #include "filemanager.h"
63 #include "panel.h"
64
65 #include "ext.h"
66
67
68
69
70
71 #ifdef USE_FILE_CMD
72 #ifdef FILE_B
73 #define FILE_CMD "file -z " FILE_B FILE_S FILE_L
74 #else
75 #define FILE_CMD "file -z " FILE_S FILE_L
76 #endif
77 #endif
78
79
80
81
82
83 #if defined(HAVE_TESTS)
84 MC_TESTABLE GString *exec_make_shell_string (const char *lc_data, const vfs_path_t *filename_vpath,
85 GString **buffer);
86
87 MC_TESTABLE GString *exec_get_export_variables (const vfs_path_t *filename_vpath);
88 #endif
89
90
91
92
93
94
95
96 static mc_config_t *ext_ini = NULL;
97 static gchar **ext_ini_groups = NULL;
98 static vfs_path_t *localfilecopy_vpath = NULL;
99
100 static time_t localmtime = 0;
101 static quote_fn quote_func = name_quote;
102 static gboolean run_view = FALSE;
103 static gboolean is_cd = FALSE;
104 static gboolean written_nonspace = FALSE;
105 static gboolean do_local_copy = FALSE;
106
107 static const char *descr_group = "mc.ext.ini";
108 static const char *default_group = "Default";
109
110
111
112
113
114 static void
115 exec_cleanup_script (vfs_path_t *script_vpath)
116 {
117 if (script_vpath != NULL)
118 {
119 (void) mc_unlink (script_vpath);
120 vfs_path_free (script_vpath, TRUE);
121 }
122 }
123
124
125
126 static void
127 exec_cleanup_file_name (const vfs_path_t *filename_vpath, gboolean has_changed)
128 {
129 if (localfilecopy_vpath == NULL)
130 return;
131
132 if (has_changed)
133 {
134 struct stat mystat;
135
136 mc_stat (localfilecopy_vpath, &mystat);
137 has_changed = localmtime != mystat.st_mtime;
138 }
139 mc_ungetlocalcopy (filename_vpath, localfilecopy_vpath, has_changed);
140 vfs_path_free (localfilecopy_vpath, TRUE);
141 localfilecopy_vpath = NULL;
142 }
143
144
145
146 static GString *
147 exec_get_file_name (const vfs_path_t *filename_vpath)
148 {
149 if (!do_local_copy)
150 return quote_func (vfs_path_get_last_path_str (filename_vpath), FALSE);
151
152 if (localfilecopy_vpath == NULL)
153 {
154 struct stat mystat;
155 localfilecopy_vpath = mc_getlocalcopy (filename_vpath);
156 if (localfilecopy_vpath == NULL)
157 return NULL;
158
159 mc_stat (localfilecopy_vpath, &mystat);
160 localmtime = mystat.st_mtime;
161 }
162
163 return quote_func (vfs_path_get_last_path_str (localfilecopy_vpath), FALSE);
164 }
165
166
167
168 static GString *
169 exec_expand_format (char symbol, gboolean is_result_quoted)
170 {
171 GString *text;
172
173 text = expand_format (NULL, symbol, TRUE);
174 if (is_result_quoted && text != NULL)
175 {
176 g_string_prepend_c (text, '"');
177 g_string_append_c (text, '"');
178 }
179 return text;
180 }
181
182
183
184 MC_TESTABLE GString *
185 exec_get_export_variables (const vfs_path_t *filename_vpath)
186 {
187 GString *text;
188 GString *export_vars_string;
189 size_t i;
190
191 struct
192 {
193 const char symbol;
194 const char *name;
195 const gboolean is_result_quoted;
196 } export_variables[] = {
197 { 'p', "MC_EXT_BASENAME", FALSE },
198 { 'd', "MC_EXT_CURRENTDIR", FALSE },
199 { 's', "MC_EXT_SELECTED", TRUE },
200 { 't', "MC_EXT_ONLYTAGGED", TRUE },
201 { '\0', NULL, FALSE },
202 };
203
204 text = exec_get_file_name (filename_vpath);
205 if (text == NULL)
206 return NULL;
207
208 export_vars_string = g_string_new ("MC_EXT_FILENAME=");
209 mc_g_string_concat (export_vars_string, text);
210 g_string_append (export_vars_string, "\nexport MC_EXT_FILENAME\n");
211 g_string_free (text, TRUE);
212
213 for (i = 0; export_variables[i].name != NULL; i++)
214 {
215 text =
216 exec_expand_format (export_variables[i].symbol, export_variables[i].is_result_quoted);
217 if (text != NULL)
218 {
219 g_string_append (export_vars_string, export_variables[i].name);
220 g_string_append_c (export_vars_string, '=');
221 mc_g_string_concat (export_vars_string, text);
222 g_string_append (export_vars_string, "\nexport ");
223 g_string_append (export_vars_string, export_variables[i].name);
224 g_string_append_c (export_vars_string, '\n');
225 g_string_free (text, TRUE);
226 }
227 }
228
229 return export_vars_string;
230 }
231
232
233
234 MC_TESTABLE GString *
235 exec_make_shell_string (const char *lc_data, const vfs_path_t *filename_vpath, GString **buffer)
236 {
237 GString *shell_string;
238 char lc_prompt[80] = "\0";
239 gboolean parameter_found = FALSE;
240 gboolean expand_prefix_found = FALSE;
241
242 shell_string = g_string_new ("");
243
244 for (; *lc_data != '\0' && *lc_data != '\n'; lc_data++)
245 {
246 if (parameter_found)
247 {
248 if (*lc_data == '}')
249 {
250 char *parameter;
251
252 parameter_found = FALSE;
253 parameter = input_dialog (_ ("Parameter"), lc_prompt, MC_HISTORY_EXT_PARAMETER, "",
254 INPUT_COMPLETE_NONE);
255 if (parameter == NULL)
256 {
257
258 g_string_free (shell_string, TRUE);
259 exec_cleanup_file_name (filename_vpath, FALSE);
260 return NULL;
261 }
262 g_string_append (shell_string, parameter);
263 written_nonspace = TRUE;
264 g_free (parameter);
265 }
266 else
267 {
268 size_t len = strlen (lc_prompt);
269
270 if (len < sizeof (lc_prompt) - 1)
271 {
272 lc_prompt[len] = *lc_data;
273 lc_prompt[len + 1] = '\0';
274 }
275 }
276 }
277 else if (expand_prefix_found)
278 {
279 expand_prefix_found = FALSE;
280 if (*lc_data == '{')
281 parameter_found = TRUE;
282 else
283 {
284 int i;
285
286 i = check_format_view (lc_data);
287 if (i != 0)
288 {
289 lc_data += i - 1;
290 run_view = TRUE;
291 }
292 else
293 {
294 i = check_format_cd (lc_data);
295 if (i > 0)
296 {
297 is_cd = TRUE;
298 quote_func = fake_name_quote;
299 do_local_copy = FALSE;
300
301 if (*buffer == NULL)
302 *buffer = g_string_sized_new (128);
303 else
304 g_string_set_size (*buffer, 0);
305
306 lc_data += i - 1;
307 }
308 else
309 {
310 char *v;
311
312 i = check_format_var (lc_data, &v);
313 if (i > 0)
314 {
315 g_string_append (shell_string, v);
316 g_free (v);
317 lc_data += i;
318 }
319 else
320 {
321 GString *text;
322
323 if (*lc_data != 'f')
324 text = expand_format (NULL, *lc_data, !is_cd);
325 else
326 {
327 text = exec_get_file_name (filename_vpath);
328 if (text == NULL)
329 {
330 g_string_free (shell_string, TRUE);
331 return NULL;
332 }
333 }
334
335 if (text != NULL)
336 {
337 if (!is_cd)
338 {
339 mc_g_string_concat (shell_string, text);
340 g_string_free (text, TRUE);
341 }
342 else if (*buffer == NULL)
343 *buffer = text;
344 else
345 {
346 mc_g_string_concat (*buffer, text);
347 g_string_free (text, TRUE);
348 }
349 }
350
351 written_nonspace = TRUE;
352 }
353 }
354 }
355 }
356 }
357 else if (*lc_data == '%')
358 expand_prefix_found = TRUE;
359 else
360 {
361 if (!whitespace (*lc_data))
362 written_nonspace = TRUE;
363 if (is_cd)
364 g_string_append_c (*buffer, *lc_data);
365 else
366 g_string_append_c (shell_string, *lc_data);
367 }
368 }
369
370 return shell_string;
371 }
372
373
374
375 static void
376 exec_extension_view (void *target, char *cmd, const vfs_path_t *filename_vpath, int start_line)
377 {
378 mcview_mode_flags_t def_flags = {
379 .wrap = FALSE,
380 .hex = mcview_global_flags.hex,
381 .magic = FALSE,
382 .nroff = mcview_global_flags.nroff,
383 };
384
385 mcview_mode_flags_t changed_flags;
386
387 mcview_clear_mode_flags (&changed_flags);
388 mcview_altered_flags.hex = FALSE;
389 mcview_altered_flags.nroff = FALSE;
390 if (def_flags.hex != mcview_global_flags.hex)
391 changed_flags.hex = TRUE;
392 if (def_flags.nroff != mcview_global_flags.nroff)
393 changed_flags.nroff = TRUE;
394
395 if (target == NULL)
396 mcview_viewer (cmd, filename_vpath, start_line, 0, 0);
397 else
398 mcview_load ((WView *) target, cmd, vfs_path_as_str (filename_vpath), start_line, 0, 0);
399
400 if (changed_flags.hex && !mcview_altered_flags.hex)
401 mcview_global_flags.hex = def_flags.hex;
402 if (changed_flags.nroff && !mcview_altered_flags.nroff)
403 mcview_global_flags.nroff = def_flags.nroff;
404
405 dialog_switch_process_pending ();
406 }
407
408
409
410 static void
411 exec_extension_cd (WPanel *panel, GString *buffer)
412 {
413 size_t i;
414 vfs_path_t *p_vpath;
415
416
417
418 for (i = buffer->len; i != 0 && whitespace (buffer->str[i - 1]); i--)
419 ;
420 g_string_set_size (buffer, i);
421
422 p_vpath = vfs_path_from_str_flags (buffer->str, VPF_NO_CANON);
423 panel_cd (panel, p_vpath, cd_parse_command);
424 vfs_path_free (p_vpath, TRUE);
425 }
426
427
428
429 static vfs_path_t *
430 exec_extension (WPanel *panel, void *target, const vfs_path_t *filename_vpath, const char *lc_data,
431 int start_line)
432 {
433 GString *shell_string, *export_variables;
434 GString *buffer = NULL;
435 vfs_path_t *script_vpath = NULL;
436 int cmd_file_fd;
437 FILE *cmd_file;
438 char *cmd = NULL;
439
440 localmtime = 0;
441 quote_func = name_quote;
442 run_view = FALSE;
443 is_cd = FALSE;
444 written_nonspace = FALSE;
445
446
447 do_local_copy = !vfs_file_is_local (filename_vpath);
448
449 shell_string = exec_make_shell_string (lc_data, filename_vpath, &buffer);
450 if (shell_string == NULL)
451 goto ret;
452
453 if (is_cd)
454 {
455 exec_extension_cd (panel, buffer);
456 g_string_free (shell_string, TRUE);
457 goto ret;
458 }
459
460
461
462
463
464
465
466 cmd_file_fd = mc_mkstemps (&script_vpath, "mcext", SCRIPT_SUFFIX);
467
468 if (cmd_file_fd == -1)
469 {
470 file_error_message (_ ("Cannot create temporary command file"), NULL);
471 g_string_free (shell_string, TRUE);
472 goto ret;
473 }
474
475 cmd_file = fdopen (cmd_file_fd, "w");
476 fputs ("#! /bin/sh\n\n", cmd_file);
477
478 export_variables = exec_get_export_variables (filename_vpath);
479 if (export_variables != NULL)
480 {
481 fputs (export_variables->str, cmd_file);
482 g_string_free (export_variables, TRUE);
483 }
484
485 fputs (shell_string->str, cmd_file);
486 g_string_free (shell_string, TRUE);
487
488
489
490
491
492
493 if (!run_view)
494 fprintf (cmd_file, "\n/bin/rm -f %s\n", vfs_path_as_str (script_vpath));
495
496 fclose (cmd_file);
497
498 if ((run_view && !written_nonspace) || is_cd)
499 {
500 exec_cleanup_script (script_vpath);
501 script_vpath = NULL;
502 }
503 else
504 {
505
506 mc_chmod (script_vpath, S_IRWXU);
507
508 cmd = g_strconcat ("/bin/sh ", vfs_path_as_str (script_vpath), (char *) NULL);
509 }
510
511 if (run_view)
512 {
513
514 if (!written_nonspace)
515 exec_extension_view (target, NULL, filename_vpath, start_line);
516 else
517 exec_extension_view (target, cmd, filename_vpath, start_line);
518 }
519 else
520 {
521 shell_execute (cmd, EXECUTE_INTERNAL);
522 if (mc_global.tty.console_flag != '\0')
523 {
524 handle_console (CONSOLE_SAVE);
525 if (output_lines != 0 && mc_global.keybar_visible)
526 {
527 unsigned char end_line;
528
529 end_line = LINES - (mc_global.keybar_visible ? 1 : 0) - 1;
530 show_console_contents (output_start_y, end_line - output_lines, end_line);
531 }
532 }
533 }
534
535 g_free (cmd);
536
537 exec_cleanup_file_name (filename_vpath, TRUE);
538 ret:
539 if (buffer != NULL)
540 g_string_free (buffer, TRUE);
541
542 return script_vpath;
543 }
544
545
546
547
548
549
550
551
552
553
554 #ifdef USE_FILE_CMD
555 static int
556 get_popen_information (const char *cmd_file, const char *args, char *buf, int buflen)
557 {
558 gboolean read_bytes = FALSE;
559 char *command;
560 FILE *f;
561
562 command = g_strconcat (cmd_file, args, " 2>/dev/null", (char *) NULL);
563 f = popen (command, "r");
564 g_free (command);
565
566 if (f != NULL)
567 {
568 #ifdef __QNXNTO__
569 if (setvbuf (f, NULL, _IOFBF, 0) != 0)
570 {
571 (void) pclose (f);
572 return -1;
573 }
574 #endif
575 read_bytes = (fgets (buf, buflen, f) != NULL);
576 if (!read_bytes)
577 buf[0] = '\0';
578 pclose (f);
579 }
580 else
581 {
582 buf[0] = '\0';
583 return -1;
584 }
585
586 buf[buflen - 1] = '\0';
587
588 return read_bytes ? 1 : 0;
589 }
590
591
592
593
594
595
596
597 static int
598 get_file_type_local (const vfs_path_t *filename_vpath, char *buf, int buflen)
599 {
600 GString *filename_quoted;
601 int ret = 0;
602
603 filename_quoted = name_quote (vfs_path_get_last_path_str (filename_vpath), FALSE);
604 if (filename_quoted != NULL)
605 {
606 ret = get_popen_information (FILE_CMD, filename_quoted->str, buf, buflen);
607 g_string_free (filename_quoted, TRUE);
608 }
609
610 return ret;
611 }
612
613
614
615
616
617
618
619 static int
620 get_file_encoding_local (const vfs_path_t *filename_vpath, char *buf, int buflen)
621 {
622 GString *filename_quoted;
623 int ret = 0;
624
625 filename_quoted = name_quote (vfs_path_get_last_path_str (filename_vpath), FALSE);
626 if (filename_quoted != NULL)
627 {
628 GString *lang;
629
630 lang = name_quote (autodetect_codeset, FALSE);
631 if (lang != NULL)
632 {
633 char *args;
634
635 args = g_strdup_printf (" -L %s -i %s", lang->str, filename_quoted->str);
636 g_string_free (lang, TRUE);
637
638 ret = get_popen_information ("enca", args, buf, buflen);
639 g_free (args);
640 }
641
642 g_string_free (filename_quoted, TRUE);
643 }
644
645 return ret;
646 }
647
648
649
650
651
652
653
654
655
656 static gboolean
657 regex_check_type (const vfs_path_t *filename_vpath, const char *ptr, gboolean case_insense,
658 gboolean *have_type, GError **mcerror)
659 {
660 gboolean found = FALSE;
661
662
663 static char content_string[BUF_2K];
664 static size_t content_shift = 0;
665 static int got_data = 0;
666
667 mc_return_val_if_error (mcerror, FALSE);
668
669 if (!*have_type)
670 {
671 vfs_path_t *localfile_vpath;
672
673 static char encoding_id[21];
674 int got_encoding_data;
675
676
677 *have_type = TRUE;
678
679 localfile_vpath = mc_getlocalcopy (filename_vpath);
680 if (localfile_vpath == NULL)
681 {
682 mc_propagate_error (mcerror, 0, _ ("Cannot fetch a local copy of %s"),
683 vfs_path_as_str (filename_vpath));
684 return FALSE;
685 }
686
687 got_encoding_data = is_autodetect_codeset_enabled
688 ? get_file_encoding_local (localfile_vpath, encoding_id, sizeof (encoding_id))
689 : 0;
690
691 if (got_encoding_data > 0)
692 {
693 char *pp;
694 int cp_id;
695
696 pp = strchr (encoding_id, '\n');
697 if (pp != NULL)
698 *pp = '\0';
699
700 cp_id = get_codepage_index (encoding_id);
701 if (cp_id == -1)
702 cp_id = default_source_codepage;
703
704 do_set_codepage (cp_id);
705 }
706
707 got_data = get_file_type_local (localfile_vpath, content_string, sizeof (content_string));
708
709 mc_ungetlocalcopy (filename_vpath, localfile_vpath, FALSE);
710
711 if (got_data > 0)
712 {
713 char *pp;
714
715 pp = strchr (content_string, '\n');
716 if (pp != NULL)
717 *pp = '\0';
718
719 #ifndef FILE_B
720 {
721 const char *real_name;
722 size_t real_len;
723
724 real_name = vfs_path_get_last_path_str (localfile_vpath);
725 real_len = strlen (real_name);
726
727 if (strncmp (content_string, real_name, real_len) == 0)
728 {
729
730 content_shift = real_len;
731
732
733 if (content_string[content_shift] == ':')
734 for (content_shift++; whitespace (content_string[content_shift]);
735 content_shift++)
736 ;
737 }
738 }
739 #endif
740 }
741 else
742 {
743
744 content_string[0] = '\0';
745 }
746 vfs_path_free (localfile_vpath, TRUE);
747 }
748
749 if (got_data == -1)
750 {
751 mc_propagate_error (mcerror, 0, "%s", _ ("Pipe failed"));
752 return FALSE;
753 }
754
755 if (content_string[0] != '\0')
756 {
757 mc_search_t *search;
758
759 search = mc_search_new (ptr, NULL);
760 if (search != NULL)
761 {
762 search->search_type = MC_SEARCH_T_REGEX;
763 search->is_case_sensitive = !case_insense;
764 found = mc_search_run (search, content_string + content_shift, 0,
765 sizeof (content_string) - 1, NULL);
766 mc_search_free (search);
767 }
768 else
769 {
770 mc_propagate_error (mcerror, 0, "%s", _ ("Regular expression error"));
771 }
772 }
773
774 return found;
775 }
776 #endif
777
778
779
780 static void
781 check_old_extension_file (void)
782 {
783 char *extension_old_file;
784
785 extension_old_file = mc_config_get_full_path (MC_EXT_OLD_FILE);
786 if (exist_file (extension_old_file))
787 message (D_ERROR, _ ("Warning"),
788 _ ("You have an outdated %s file.\n%s now uses %s file.\n"
789 "Please copy your modifications of the old file to the new one."),
790 extension_old_file, PACKAGE_NAME, MC_EXT_FILE);
791 g_free (extension_old_file);
792 }
793
794
795
796 static gboolean
797 load_extension_file (void)
798 {
799 char *extension_file;
800 gboolean mc_user_ext = TRUE;
801 gboolean home_error = FALSE;
802
803 extension_file = mc_config_get_full_path (MC_EXT_FILE);
804 if (!exist_file (extension_file))
805 {
806 g_free (extension_file);
807
808 check_old_extension_file ();
809
810 check_stock_mc_ext:
811 extension_file = mc_build_filename (mc_global.sysconfig_dir, MC_EXT_FILE, (char *) NULL);
812 if (!exist_file (extension_file))
813 {
814 g_free (extension_file);
815 extension_file =
816 mc_build_filename (mc_global.share_data_dir, MC_EXT_FILE, (char *) NULL);
817 if (!exist_file (extension_file))
818 MC_PTR_FREE (extension_file);
819 }
820 mc_user_ext = FALSE;
821 }
822
823 if (extension_file != NULL)
824 {
825 ext_ini = mc_config_init (extension_file, TRUE);
826 g_free (extension_file);
827 }
828 if (ext_ini == NULL)
829 return FALSE;
830
831
832 if (!mc_config_has_group (ext_ini, descr_group))
833 {
834 flush_extension_file ();
835
836 if (!mc_user_ext)
837 {
838 message (D_ERROR, MSG_ERROR,
839 _ ("The format of the\n%s%s\nfile has changed with version 4.0.\n"
840 "It seems that the installation has failed.\nPlease fetch a fresh copy "
841 "from the %s package."),
842 mc_global.sysconfig_dir, MC_EXT_FILE, PACKAGE_NAME);
843 return FALSE;
844 }
845
846 home_error = TRUE;
847 goto check_stock_mc_ext;
848 }
849
850 if (home_error)
851 {
852 extension_file = mc_config_get_full_path (MC_EXT_FILE);
853 message (
854 D_ERROR, MSG_ERROR,
855 _ ("The format of the\n%s\nfile has changed with version 4.0.\nYou may either want "
856 "to copy it from\n%s%s\nor use that file as an example of how to write it."),
857 extension_file, mc_global.sysconfig_dir, MC_EXT_FILE);
858 g_free (extension_file);
859 }
860
861 return TRUE;
862 }
863
864
865
866
867
868 void
869 flush_extension_file (void)
870 {
871 g_strfreev (ext_ini_groups);
872 ext_ini_groups = NULL;
873
874 mc_config_deinit (ext_ini);
875 ext_ini = NULL;
876 }
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893 int
894 regex_command_for (void *target, const vfs_path_t *filename_vpath, const char *action,
895 vfs_path_t **script_vpath)
896 {
897 const char *filename;
898 size_t filename_len;
899 gboolean found = FALSE;
900 gboolean error_flag = FALSE;
901 int ret = 0;
902 struct stat mystat;
903 int view_at_line_number = 0;
904 #ifdef USE_FILE_CMD
905 gboolean have_type = FALSE;
906 #endif
907 char **group_iter;
908 char *include_group = NULL;
909 const char *current_group;
910
911 if (filename_vpath == NULL)
912 return 0;
913
914 if (script_vpath != NULL)
915 *script_vpath = NULL;
916
917
918 if (strncmp (action, "View:", 5) == 0)
919 {
920 view_at_line_number = atoi (action + 5);
921 action = "View";
922 }
923
924 if (ext_ini == NULL && !load_extension_file ())
925 return 0;
926
927 mc_stat (filename_vpath, &mystat);
928
929 filename = vfs_path_get_last_path_str (filename_vpath);
930 filename = x_basename (filename);
931 filename_len = strlen (filename);
932
933 if (ext_ini_groups == NULL)
934 ext_ini_groups = mc_config_get_groups (ext_ini, NULL);
935
936
937 for (group_iter = ext_ini_groups; *group_iter != NULL && !found; group_iter++)
938 {
939 enum
940 {
941 TYPE_UNUSED,
942 TYPE_NOT_FOUND,
943 TYPE_FOUND
944 } type_state = TYPE_UNUSED;
945
946 const gchar *g = *group_iter;
947 gchar *pattern;
948 gboolean ignore_case;
949
950 if (strcmp (g, descr_group) == 0 || strncmp (g, "Include/", 8) == 0
951 || strcmp (g, default_group) == 0)
952 continue;
953
954
955
956 pattern = mc_config_get_string_raw (ext_ini, g, "Directory", NULL);
957 if (pattern != NULL)
958 {
959 found = S_ISDIR (mystat.st_mode)
960 && mc_search (pattern, NULL, vfs_path_as_str (filename_vpath), MC_SEARCH_T_REGEX);
961 g_free (pattern);
962
963 continue;
964 }
965
966 #ifdef USE_FILE_CMD
967 if (use_file_to_check_type)
968 {
969 pattern = mc_config_get_string_raw (ext_ini, g, "Type", NULL);
970 if (pattern != NULL)
971 {
972 GError *mcerror = NULL;
973
974 ignore_case = mc_config_get_bool (ext_ini, g, "TypeIgnoreCase", FALSE);
975 type_state =
976 regex_check_type (filename_vpath, pattern, ignore_case, &have_type, &mcerror)
977 ? TYPE_FOUND
978 : TYPE_NOT_FOUND;
979 g_free (pattern);
980
981 if (mc_error_message (&mcerror, NULL))
982 error_flag = TRUE;
983
984 if (type_state == TYPE_NOT_FOUND)
985 continue;
986 }
987 }
988 #endif
989
990 pattern = mc_config_get_string_raw (ext_ini, g, "Regex", NULL);
991 if (pattern != NULL)
992 {
993 mc_search_t *search;
994
995 ignore_case = mc_config_get_bool (ext_ini, g, "RegexIgnoreCase", FALSE);
996 search = mc_search_new (pattern, NULL);
997 g_free (pattern);
998
999 if (search != NULL)
1000 {
1001 search->search_type = MC_SEARCH_T_REGEX;
1002 search->is_case_sensitive = !ignore_case;
1003 found = mc_search_run (search, filename, 0, filename_len, NULL);
1004 mc_search_free (search);
1005 }
1006
1007 found = found && (type_state == TYPE_UNUSED || type_state == TYPE_FOUND);
1008 }
1009 else
1010 {
1011 pattern = mc_config_get_string_raw (ext_ini, g, "Shell", NULL);
1012 if (pattern != NULL)
1013 {
1014 int (*cmp_func) (const char *s1, const char *s2, size_t n);
1015 size_t pattern_len;
1016
1017 ignore_case = mc_config_get_bool (ext_ini, g, "ShellIgnoreCase", FALSE);
1018 cmp_func = ignore_case ? strncasecmp : strncmp;
1019 pattern_len = strlen (pattern);
1020
1021 if (*pattern == '.' && filename_len >= pattern_len)
1022 found =
1023 cmp_func (pattern, filename + filename_len - pattern_len, pattern_len) == 0;
1024 else
1025 found = pattern_len == filename_len
1026 && cmp_func (pattern, filename, filename_len) == 0;
1027
1028 g_free (pattern);
1029
1030 found = found && (type_state == TYPE_UNUSED || type_state == TYPE_FOUND);
1031 }
1032 else
1033 found = type_state == TYPE_FOUND;
1034 }
1035 }
1036
1037
1038 if (found)
1039 {
1040 char *include_value;
1041
1042 group_iter--;
1043
1044
1045 include_value = mc_config_get_string_raw (ext_ini, *group_iter, "Include", NULL);
1046 if (include_value != NULL)
1047 {
1048
1049 include_group = g_strconcat ("Include/", include_value, (char *) NULL);
1050 g_free (include_value);
1051 found = mc_config_has_group (ext_ini, include_group);
1052 }
1053 }
1054
1055 if (found)
1056 current_group = include_group != NULL ? include_group : *group_iter;
1057 else
1058 {
1059 current_group = default_group;
1060 found = mc_config_has_group (ext_ini, current_group);
1061 }
1062
1063 if (found && !error_flag)
1064 {
1065 gchar *action_value;
1066
1067 action_value = mc_config_get_string_raw (ext_ini, current_group, action, NULL);
1068 if (action_value == NULL)
1069 {
1070
1071 action_value = mc_config_get_string_raw (ext_ini, default_group, action, NULL);
1072 found = (action_value != NULL && *action_value != '\0');
1073 }
1074 else
1075 {
1076
1077 found = (*action_value != '\0');
1078 }
1079
1080 if (found)
1081 {
1082 vfs_path_t *sv;
1083
1084 sv = exec_extension (current_panel, target, filename_vpath, action_value,
1085 view_at_line_number);
1086 if (script_vpath != NULL)
1087 *script_vpath = sv;
1088 else
1089 exec_cleanup_script (sv);
1090
1091 ret = 1;
1092 }
1093
1094 g_free (action_value);
1095 }
1096
1097 g_free (include_group);
1098
1099 return (error_flag ? -1 : ret);
1100 }
1101
1102