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