root/src/execute.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. edition_post_exec
  2. edition_pre_exec
  3. do_possible_cd
  4. do_suspend_cmd
  5. execute_prepare_with_vfs_arg
  6. execute_cleanup_with_vfs_arg
  7. execute_get_opts_from_cfg
  8. execute_get_external_cmd_opts_from_config
  9. do_executev
  10. do_execute
  11. pre_exec
  12. post_exec
  13. shell_execute
  14. toggle_subshell
  15. execute_suspend
  16. execute_with_vfs_arg
  17. execute_external_editor_or_viewer

   1 /*
   2    Execution routines for GNU Midnight Commander
   3 
   4    Copyright (C) 2003-2024
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Slava Zanko <slavazanko@gmail.com>, 2013
   9 
  10    This file is part of the Midnight Commander.
  11 
  12    The Midnight Commander is free software: you can redistribute it
  13    and/or modify it under the terms of the GNU General Public License as
  14    published by the Free Software Foundation, either version 3 of the License,
  15    or (at your option) any later version.
  16 
  17    The Midnight Commander is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21 
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24  */
  25 
  26 /** \file  execute.c
  27  *  \brief Source: execution routines
  28  */
  29 
  30 #include <config.h>
  31 
  32 #include <signal.h>
  33 #include <string.h>
  34 #include <sys/stat.h>
  35 #include <sys/time.h>
  36 
  37 #include "lib/global.h"
  38 
  39 #include "lib/tty/tty.h"
  40 #include "lib/tty/key.h"
  41 #include "lib/tty/win.h"
  42 #include "lib/vfs/vfs.h"
  43 #include "lib/mcconfig.h"
  44 #include "lib/util.h"
  45 #include "lib/strutil.h"        /* str_replace_all_substrings() */
  46 #include "lib/widget.h"
  47 
  48 #include "filemanager/filemanager.h"
  49 #include "filemanager/layout.h" /* use_dash() */
  50 #include "consaver/cons.saver.h"
  51 #ifdef ENABLE_SUBSHELL
  52 #include "subshell/subshell.h"
  53 #endif
  54 #include "setup.h"              /* clear_before_exec */
  55 
  56 #include "execute.h"
  57 
  58 /*** global variables ****************************************************************************/
  59 
  60 int pause_after_run = pause_on_dumb_terminals;
  61 
  62 /*** file scope macro definitions ****************************************************************/
  63 
  64 /*** file scope type declarations ****************************************************************/
  65 
  66 /*** forward declarations (file scope functions) *************************************************/
  67 
  68 void do_execute (const char *shell, const char *command, int flags);
  69 void do_executev (const char *shell, int flags, char *const argv[]);
  70 char *execute_get_external_cmd_opts_from_config (const char *command,
  71                                                  const vfs_path_t * filename_vpath,
  72                                                  long start_line);
  73 
  74 /*** file scope variables ************************************************************************/
  75 
  76 /* --------------------------------------------------------------------------------------------- */
  77 /*** file scope functions ************************************************************************/
  78 /* --------------------------------------------------------------------------------------------- */
  79 
  80 static void
  81 edition_post_exec (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  82 {
  83     tty_enter_ca_mode ();
  84 
  85     /* FIXME: Missing on slang endwin? */
  86     tty_reset_prog_mode ();
  87     tty_flush_input ();
  88 
  89     tty_keypad (TRUE);
  90     tty_raw_mode ();
  91     channels_up ();
  92     enable_mouse ();
  93     enable_bracketed_paste ();
  94     if (mc_global.tty.alternate_plus_minus)
  95         application_keypad_mode ();
  96 }
  97 
  98 /* --------------------------------------------------------------------------------------------- */
  99 
 100 static void
 101 edition_pre_exec (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 102 {
 103     if (clear_before_exec)
 104         tty_clear_screen ();
 105     else
 106     {
 107         if (!(mc_global.tty.console_flag != '\0' || mc_global.tty.xterm_flag))
 108             printf ("\n\n");
 109     }
 110 
 111     channels_down ();
 112     disable_mouse ();
 113     disable_bracketed_paste ();
 114 
 115     tty_reset_shell_mode ();
 116     tty_keypad (FALSE);
 117     tty_reset_screen ();
 118 
 119     numeric_keypad_mode ();
 120 
 121     /* on xterms: maybe endwin did not leave the terminal on the shell
 122      * screen page: do it now.
 123      *
 124      * Do not move this before endwin: in some systems rmcup includes
 125      * a call to clear screen, so it will end up clearing the shell screen.
 126      */
 127     tty_exit_ca_mode ();
 128 }
 129 
 130 /* --------------------------------------------------------------------------------------------- */
 131 
 132 #ifdef ENABLE_SUBSHELL
 133 static void
 134 do_possible_cd (const vfs_path_t * new_dir_vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 135 {
 136     if (!panel_cd (current_panel, new_dir_vpath, cd_exact))
 137         message (D_ERROR, _("Warning"), "%s",
 138                  _("The Commander can't change to the directory that\n"
 139                    "the subshell claims you are in. Perhaps you have\n"
 140                    "deleted your working directory, or given yourself\n"
 141                    "extra access permissions with the \"su\" command?"));
 142 }
 143 #endif /* ENABLE_SUBSHELL */
 144 
 145 /* --------------------------------------------------------------------------------------------- */
 146 
 147 static void
 148 do_suspend_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 149 {
 150     pre_exec ();
 151 
 152     if (mc_global.tty.console_flag != '\0' && !mc_global.tty.use_subshell)
 153         handle_console (CONSOLE_RESTORE);
 154 
 155 #ifdef SIGTSTP
 156     {
 157         struct sigaction sigtstp_action;
 158 
 159         memset (&sigtstp_action, 0, sizeof (sigtstp_action));
 160         /* Make sure that the SIGTSTP below will suspend us directly,
 161            without calling ncurses' SIGTSTP handler; we *don't* want
 162            ncurses to redraw the screen immediately after the SIGCONT */
 163         sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
 164 
 165         kill (getpid (), SIGTSTP);
 166 
 167         /* Restore previous SIGTSTP action */
 168         sigaction (SIGTSTP, &sigtstp_action, NULL);
 169     }
 170 #endif /* SIGTSTP */
 171 
 172     if (mc_global.tty.console_flag != '\0' && !mc_global.tty.use_subshell)
 173         handle_console (CONSOLE_SAVE);
 174 
 175     edition_post_exec ();
 176 }
 177 
 178 /* --------------------------------------------------------------------------------------------- */
 179 
 180 static gboolean
 181 execute_prepare_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** localcopy_vpath,
     /* [previous][next][first][last][top][bottom][index][help]  */
 182                               time_t * mtime)
 183 {
 184     struct stat st;
 185 
 186     /* Simplest case, this file is local */
 187     if ((filename_vpath == NULL && vfs_file_is_local (vfs_get_raw_current_dir ()))
 188         || vfs_file_is_local (filename_vpath))
 189         return TRUE;
 190 
 191     /* FIXME: Creation of new files on VFS is not supported */
 192     if (filename_vpath == NULL)
 193         return FALSE;
 194 
 195     *localcopy_vpath = mc_getlocalcopy (filename_vpath);
 196     if (*localcopy_vpath == NULL)
 197     {
 198         message (D_ERROR, MSG_ERROR, _("Cannot fetch a local copy of %s"),
 199                  vfs_path_as_str (filename_vpath));
 200         return FALSE;
 201     }
 202 
 203     mc_stat (*localcopy_vpath, &st);
 204     *mtime = st.st_mtime;
 205     return TRUE;
 206 }
 207 
 208 /* --------------------------------------------------------------------------------------------- */
 209 
 210 static void
 211 execute_cleanup_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** localcopy_vpath,
     /* [previous][next][first][last][top][bottom][index][help]  */
 212                               time_t * mtime)
 213 {
 214     if (*localcopy_vpath != NULL)
 215     {
 216         struct stat st;
 217 
 218         /*
 219          * filename can be an entry on panel, it can be changed by executing
 220          * the command, so make a copy.  Smarter VFS code would make the code
 221          * below unnecessary.
 222          */
 223         mc_stat (*localcopy_vpath, &st);
 224         mc_ungetlocalcopy (filename_vpath, *localcopy_vpath, *mtime != st.st_mtime);
 225         vfs_path_free (*localcopy_vpath, TRUE);
 226         *localcopy_vpath = NULL;
 227     }
 228 }
 229 
 230 /* --------------------------------------------------------------------------------------------- */
 231 
 232 static char *
 233 execute_get_opts_from_cfg (const char *command, const char *default_str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 234 {
 235     char *str_from_config;
 236 
 237     str_from_config =
 238         mc_config_get_string_raw (mc_global.main_config, CONFIG_EXT_EDITOR_VIEWER_SECTION, command,
 239                                   NULL);
 240 
 241     if (str_from_config == NULL)
 242     {
 243         mc_config_t *cfg;
 244 
 245         cfg = mc_config_init (mc_global.profile_name, TRUE);
 246         if (cfg == NULL)
 247             return g_strdup (default_str);
 248 
 249         str_from_config =
 250             mc_config_get_string_raw (cfg, CONFIG_EXT_EDITOR_VIEWER_SECTION, command, default_str);
 251 
 252         mc_config_deinit (cfg);
 253     }
 254 
 255     return str_from_config;
 256 }
 257 
 258 /* --------------------------------------------------------------------------------------------- */
 259 /*** public functions ****************************************************************************/
 260 /* --------------------------------------------------------------------------------------------- */
 261 
 262 char *
 263 execute_get_external_cmd_opts_from_config (const char *command, const vfs_path_t * filename_vpath,
     /* [previous][next][first][last][top][bottom][index][help]  */
 264                                            long start_line)
 265 {
 266     char *str_from_config, *return_str;
 267     char *parameter;
 268 
 269     if (filename_vpath == NULL)
 270         return g_strdup ("");
 271 
 272     parameter = g_shell_quote (vfs_path_get_last_path_str (filename_vpath));
 273 
 274     if (start_line <= 0)
 275         return parameter;
 276 
 277     str_from_config = execute_get_opts_from_cfg (command, "%filename");
 278 
 279     return_str = str_replace_all (str_from_config, "%filename", parameter);
 280     g_free (parameter);
 281     g_free (str_from_config);
 282     str_from_config = return_str;
 283 
 284     parameter = g_strdup_printf ("%ld", start_line);
 285     return_str = str_replace_all (str_from_config, "%lineno", parameter);
 286     g_free (parameter);
 287     g_free (str_from_config);
 288 
 289     return return_str;
 290 }
 291 
 292 /* --------------------------------------------------------------------------------------------- */
 293 
 294 void
 295 do_executev (const char *shell, int flags, char *const argv[])
     /* [previous][next][first][last][top][bottom][index][help]  */
 296 {
 297 #ifdef ENABLE_SUBSHELL
 298     vfs_path_t *new_dir_vpath = NULL;
 299 #endif /* ENABLE_SUBSHELL */
 300 
 301     vfs_path_t *old_vfs_dir_vpath = NULL;
 302 
 303     if (!vfs_current_is_local ())
 304         old_vfs_dir_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
 305 
 306     if (mc_global.mc_run_mode == MC_RUN_FULL)
 307         save_cwds_stat ();
 308     pre_exec ();
 309     if (mc_global.tty.console_flag != '\0')
 310         handle_console (CONSOLE_RESTORE);
 311 
 312     if (!mc_global.tty.use_subshell && *argv != NULL && (flags & EXECUTE_INTERNAL) == 0)
 313     {
 314         printf ("%s%s\n", mc_prompt, *argv);
 315         fflush (stdout);
 316     }
 317 #ifdef ENABLE_SUBSHELL
 318     if (mc_global.tty.use_subshell && (flags & EXECUTE_INTERNAL) == 0)
 319     {
 320         do_update_prompt ();
 321 
 322         /* We don't care if it died, higher level takes care of this */
 323         invoke_subshell (*argv, VISIBLY, old_vfs_dir_vpath != NULL ? NULL : &new_dir_vpath);
 324     }
 325     else
 326 #endif /* ENABLE_SUBSHELL */
 327         my_systemv_flags (flags, shell, argv);
 328 
 329     if ((flags & EXECUTE_INTERNAL) == 0)
 330     {
 331         if ((pause_after_run == pause_always
 332              || (pause_after_run == pause_on_dumb_terminals && !mc_global.tty.xterm_flag
 333                  && mc_global.tty.console_flag == '\0')) && quit == 0
 334 #ifdef ENABLE_SUBSHELL
 335             && subshell_state != RUNNING_COMMAND
 336 #endif /* ENABLE_SUBSHELL */
 337             )
 338         {
 339             printf ("%s", _("Press any key to continue..."));
 340             fflush (stdout);
 341             tty_raw_mode ();
 342             get_key_code (0);
 343             printf ("\r\n");
 344             fflush (stdout);
 345         }
 346         if (mc_global.tty.console_flag != '\0' && output_lines != 0 && mc_global.keybar_visible)
 347         {
 348             putchar ('\n');
 349             fflush (stdout);
 350         }
 351     }
 352 
 353     if (mc_global.tty.console_flag != '\0')
 354         handle_console (CONSOLE_SAVE);
 355     edition_post_exec ();
 356 
 357 #ifdef ENABLE_SUBSHELL
 358     if (new_dir_vpath != NULL)
 359     {
 360         do_possible_cd (new_dir_vpath);
 361         vfs_path_free (new_dir_vpath, TRUE);
 362     }
 363 
 364 #endif /* ENABLE_SUBSHELL */
 365 
 366     if (old_vfs_dir_vpath != NULL)
 367     {
 368         mc_chdir (old_vfs_dir_vpath);
 369         vfs_path_free (old_vfs_dir_vpath, TRUE);
 370     }
 371 
 372     if (mc_global.mc_run_mode == MC_RUN_FULL)
 373     {
 374         update_panels (UP_OPTIMIZE, UP_KEEPSEL);
 375         update_xterm_title_path ();
 376         update_terminal_cwd ();
 377     }
 378 
 379     do_refresh ();
 380     use_dash (TRUE);
 381 }
 382 
 383 /* --------------------------------------------------------------------------------------------- */
 384 
 385 void
 386 do_execute (const char *shell, const char *command, int flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 387 {
 388     GPtrArray *args_array;
 389 
 390     args_array = g_ptr_array_new ();
 391     g_ptr_array_add (args_array, (char *) command);
 392     g_ptr_array_add (args_array, NULL);
 393 
 394     do_executev (shell, flags, (char *const *) args_array->pdata);
 395 
 396     g_ptr_array_free (args_array, TRUE);
 397 }
 398 
 399 /* --------------------------------------------------------------------------------------------- */
 400 
 401 /** Set up the terminal before executing a program */
 402 
 403 void
 404 pre_exec (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 405 {
 406     use_dash (FALSE);
 407     edition_pre_exec ();
 408 }
 409 
 410 /* --------------------------------------------------------------------------------------------- */
 411 /** Hide the terminal after executing a program */
 412 void
 413 post_exec (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 414 {
 415     edition_post_exec ();
 416     use_dash (TRUE);
 417     repaint_screen ();
 418 }
 419 
 420 /* --------------------------------------------------------------------------------------------- */
 421 /* Executes a command */
 422 
 423 void
 424 shell_execute (const char *command, int flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 425 {
 426     char *cmd = NULL;
 427 
 428     if (flags & EXECUTE_HIDE)
 429     {
 430         cmd = g_strconcat (" ", command, (char *) NULL);
 431         flags ^= EXECUTE_HIDE;
 432     }
 433 
 434 #ifdef ENABLE_SUBSHELL
 435     if (mc_global.tty.use_subshell)
 436     {
 437         if (subshell_state == INACTIVE)
 438             do_execute (mc_global.shell->path, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
 439         else
 440             message (D_ERROR, MSG_ERROR, "%s", _("The shell is already running a command"));
 441     }
 442     else
 443 #endif /* ENABLE_SUBSHELL */
 444         do_execute (mc_global.shell->path, cmd ? cmd : command, flags | EXECUTE_AS_SHELL);
 445 
 446     g_free (cmd);
 447 }
 448 
 449 /* --------------------------------------------------------------------------------------------- */
 450 
 451 void
 452 toggle_subshell (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 453 {
 454     static gboolean message_flag = TRUE;
 455 
 456 #ifdef ENABLE_SUBSHELL
 457     vfs_path_t *new_dir_vpath = NULL;
 458 #endif /* ENABLE_SUBSHELL */
 459 
 460     SIG_ATOMIC_VOLATILE_T was_sigwinch = 0;
 461 
 462     if (!(mc_global.tty.xterm_flag || mc_global.tty.console_flag != '\0'
 463           || mc_global.tty.use_subshell || output_starts_shell))
 464     {
 465         if (message_flag)
 466             message (D_ERROR, MSG_ERROR,
 467                      _("Not an xterm or Linux console;\nthe subshell cannot be toggled."));
 468         message_flag = FALSE;
 469         return;
 470     }
 471 
 472     channels_down ();
 473     disable_mouse ();
 474     disable_bracketed_paste ();
 475     if (clear_before_exec)
 476         tty_clear_screen ();
 477     if (mc_global.tty.alternate_plus_minus)
 478         numeric_keypad_mode ();
 479 #ifndef HAVE_SLANG
 480     /* With slang we don't want any of this, since there
 481      * is no raw_mode supported
 482      */
 483     tty_reset_shell_mode ();
 484 #endif /* !HAVE_SLANG */
 485     tty_noecho ();
 486     tty_keypad (FALSE);
 487     tty_reset_screen ();
 488     tty_exit_ca_mode ();
 489     tty_raw_mode ();
 490     if (mc_global.tty.console_flag != '\0')
 491         handle_console (CONSOLE_RESTORE);
 492 
 493 #ifdef ENABLE_SUBSHELL
 494     if (mc_global.tty.use_subshell)
 495     {
 496         vfs_path_t **new_dir_p;
 497 
 498         new_dir_p = vfs_current_is_local ()? &new_dir_vpath : NULL;
 499         invoke_subshell (NULL, VISIBLY, new_dir_p);
 500     }
 501     else
 502 #endif /* ENABLE_SUBSHELL */
 503     {
 504         if (output_starts_shell)
 505         {
 506             fputs (_("Type 'exit' to return to the Midnight Commander"), stderr);
 507             fputs ("\n\r\n\r", stderr);
 508 
 509             my_system (EXECUTE_INTERNAL, mc_global.shell->path, NULL);
 510         }
 511         else
 512             get_key_code (0);
 513     }
 514 
 515     if (mc_global.tty.console_flag != '\0')
 516         handle_console (CONSOLE_SAVE);
 517 
 518     tty_enter_ca_mode ();
 519 
 520     tty_reset_prog_mode ();
 521     tty_keypad (TRUE);
 522 
 523     /* Prevent screen flash when user did 'exit' or 'logout' within
 524        subshell */
 525     if ((quit & SUBSHELL_EXIT) != 0)
 526     {
 527         /* User did 'exit' or 'logout': quit MC */
 528         if (quiet_quit_cmd ())
 529             return;
 530 
 531         quit = 0;
 532 #ifdef ENABLE_SUBSHELL
 533         /* restart subshell */
 534         if (mc_global.tty.use_subshell)
 535             init_subshell ();
 536 #endif /* ENABLE_SUBSHELL */
 537     }
 538 
 539     enable_mouse ();
 540     enable_bracketed_paste ();
 541     channels_up ();
 542     if (mc_global.tty.alternate_plus_minus)
 543         application_keypad_mode ();
 544 
 545     /* HACK:
 546      * Save sigwinch flag that will be reset in mc_refresh() called via update_panels().
 547      * There is some problem with screen redraw in ncurses-based mc in this situation.
 548      */
 549     was_sigwinch = tty_got_winch ();
 550     tty_flush_winch ();
 551 
 552 #ifdef ENABLE_SUBSHELL
 553     if (mc_global.tty.use_subshell)
 554     {
 555         if (mc_global.mc_run_mode == MC_RUN_FULL)
 556         {
 557             if (new_dir_vpath != NULL)
 558                 do_possible_cd (new_dir_vpath);
 559         }
 560         else if (new_dir_vpath != NULL && mc_chdir (new_dir_vpath) != -1)
 561             vfs_setup_cwd ();
 562     }
 563 
 564     vfs_path_free (new_dir_vpath, TRUE);
 565 #endif /* ENABLE_SUBSHELL */
 566 
 567     if (mc_global.mc_run_mode == MC_RUN_FULL)
 568     {
 569         update_panels (UP_OPTIMIZE, UP_KEEPSEL);
 570         update_xterm_title_path ();
 571         update_terminal_cwd ();
 572     }
 573 
 574     if (was_sigwinch != 0 || tty_got_winch ())
 575         dialog_change_screen_size ();
 576     else
 577         repaint_screen ();
 578 }
 579 
 580 /* --------------------------------------------------------------------------------------------- */
 581 
 582 /* event callback */
 583 gboolean
 584 execute_suspend (const gchar * event_group_name, const gchar * event_name,
     /* [previous][next][first][last][top][bottom][index][help]  */
 585                  gpointer init_data, gpointer data)
 586 {
 587     (void) event_group_name;
 588     (void) event_name;
 589     (void) init_data;
 590     (void) data;
 591 
 592     if (mc_global.mc_run_mode == MC_RUN_FULL)
 593         save_cwds_stat ();
 594     do_suspend_cmd ();
 595     if (mc_global.mc_run_mode == MC_RUN_FULL)
 596         update_panels (UP_OPTIMIZE, UP_KEEPSEL);
 597     do_refresh ();
 598 
 599     return TRUE;
 600 }
 601 
 602 /* --------------------------------------------------------------------------------------------- */
 603 
 604 /**
 605  * Execute command on a filename that can be on VFS.
 606  * Errors are reported to the user.
 607  */
 608 
 609 void
 610 execute_with_vfs_arg (const char *command, const vfs_path_t * filename_vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 611 {
 612     vfs_path_t *localcopy_vpath = NULL;
 613     const vfs_path_t *do_execute_vpath;
 614     time_t mtime;
 615 
 616     if (!execute_prepare_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime))
 617         return;
 618 
 619     do_execute_vpath = (localcopy_vpath == NULL) ? filename_vpath : localcopy_vpath;
 620 
 621     do_execute (command, vfs_path_get_last_path_str (do_execute_vpath), EXECUTE_INTERNAL);
 622 
 623     execute_cleanup_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime);
 624 }
 625 
 626 /* --------------------------------------------------------------------------------------------- */
 627 /**
 628  * Execute external editor or viewer.
 629  *
 630  * @param command editor/viewer to run
 631  * @param filename_vpath path for edit/view
 632  * @param start_line cursor will be placed at the 'start_line' position after opening file
 633  *        if start_line is 0 or negative, no start line will be passed to editor/viewer
 634  */
 635 
 636 void
 637 execute_external_editor_or_viewer (const char *command, const vfs_path_t * filename_vpath,
     /* [previous][next][first][last][top][bottom][index][help]  */
 638                                    long start_line)
 639 {
 640     vfs_path_t *localcopy_vpath = NULL;
 641     const vfs_path_t *do_execute_vpath;
 642     char *extern_cmd_options;
 643     time_t mtime = 0;
 644 
 645     if (!execute_prepare_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime))
 646         return;
 647 
 648     do_execute_vpath = (localcopy_vpath == NULL) ? filename_vpath : localcopy_vpath;
 649 
 650     extern_cmd_options =
 651         execute_get_external_cmd_opts_from_config (command, do_execute_vpath, start_line);
 652 
 653     if (extern_cmd_options != NULL)
 654     {
 655         char **argv_cmd_options;
 656         int argv_count;
 657 
 658         if (g_shell_parse_argv (extern_cmd_options, &argv_count, &argv_cmd_options, NULL))
 659         {
 660             do_executev (command, EXECUTE_INTERNAL, argv_cmd_options);
 661             g_strfreev (argv_cmd_options);
 662         }
 663         else
 664             do_executev (command, EXECUTE_INTERNAL, NULL);
 665 
 666         g_free (extern_cmd_options);
 667     }
 668 
 669     execute_cleanup_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime);
 670 }
 671 
 672 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */