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