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 MC_MOCKABLE void do_execute (const char *shell, const char *command, int flags);
  69 MC_MOCKABLE void do_executev (const char *shell, int flags, char *const argv[]);
  70 MC_MOCKABLE 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         my_sigaction (SIGTSTP, &startup_handler, &sigtstp_action);
 164 
 165         kill (getpid (), SIGTSTP);
 166 
 167         /* Restore previous SIGTSTP action */
 168         my_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) != 0)
 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 != NULL ? cmd : command,
 439                         flags | EXECUTE_AS_SHELL);
 440         else
 441             message (D_ERROR, MSG_ERROR, "%s", _("The shell is already running a command"));
 442     }
 443     else
 444 #endif /* ENABLE_SUBSHELL */
 445         do_execute (mc_global.shell->path, cmd != NULL ? cmd : command, flags | EXECUTE_AS_SHELL);
 446 
 447     g_free (cmd);
 448 }
 449 
 450 /* --------------------------------------------------------------------------------------------- */
 451 
 452 void
 453 toggle_subshell (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 454 {
 455     static gboolean message_flag = TRUE;
 456 
 457 #ifdef ENABLE_SUBSHELL
 458     vfs_path_t *new_dir_vpath = NULL;
 459 #endif /* ENABLE_SUBSHELL */
 460 
 461     SIG_ATOMIC_VOLATILE_T was_sigwinch = 0;
 462 
 463     if (!(mc_global.tty.xterm_flag || mc_global.tty.console_flag != '\0'
 464           || mc_global.tty.use_subshell || output_starts_shell))
 465     {
 466         if (message_flag)
 467             message (D_ERROR, MSG_ERROR,
 468                      _("Not an xterm or Linux console;\nthe subshell cannot be toggled."));
 469         message_flag = FALSE;
 470         return;
 471     }
 472 
 473     channels_down ();
 474     disable_mouse ();
 475     disable_bracketed_paste ();
 476     if (clear_before_exec)
 477         tty_clear_screen ();
 478     if (mc_global.tty.alternate_plus_minus)
 479         numeric_keypad_mode ();
 480 #ifndef HAVE_SLANG
 481     /* With slang we don't want any of this, since there
 482      * is no raw_mode supported
 483      */
 484     tty_reset_shell_mode ();
 485 #endif /* !HAVE_SLANG */
 486     tty_noecho ();
 487     tty_keypad (FALSE);
 488     tty_reset_screen ();
 489     tty_exit_ca_mode ();
 490     tty_raw_mode ();
 491     if (mc_global.tty.console_flag != '\0')
 492         handle_console (CONSOLE_RESTORE);
 493 
 494 #ifdef ENABLE_SUBSHELL
 495     if (mc_global.tty.use_subshell)
 496     {
 497         vfs_path_t **new_dir_p;
 498 
 499         new_dir_p = vfs_current_is_local ()? &new_dir_vpath : NULL;
 500         invoke_subshell (NULL, VISIBLY, new_dir_p);
 501     }
 502     else
 503 #endif /* ENABLE_SUBSHELL */
 504     {
 505         if (output_starts_shell)
 506         {
 507             fputs (_("Type 'exit' to return to the Midnight Commander"), stderr);
 508             fputs ("\n\r\n\r", stderr);
 509 
 510             my_system (EXECUTE_INTERNAL, mc_global.shell->path, NULL);
 511         }
 512         else
 513             get_key_code (0);
 514     }
 515 
 516     if (mc_global.tty.console_flag != '\0')
 517         handle_console (CONSOLE_SAVE);
 518 
 519     tty_enter_ca_mode ();
 520 
 521     tty_reset_prog_mode ();
 522     tty_keypad (TRUE);
 523 
 524     /* Prevent screen flash when user did 'exit' or 'logout' within
 525        subshell */
 526     if ((quit & SUBSHELL_EXIT) != 0)
 527     {
 528         /* User did 'exit' or 'logout': quit MC */
 529         if (quiet_quit_cmd ())
 530             return;
 531 
 532         quit = 0;
 533 #ifdef ENABLE_SUBSHELL
 534         /* restart subshell */
 535         if (mc_global.tty.use_subshell)
 536             init_subshell ();
 537 #endif /* ENABLE_SUBSHELL */
 538     }
 539 
 540     enable_mouse ();
 541     enable_bracketed_paste ();
 542     channels_up ();
 543     if (mc_global.tty.alternate_plus_minus)
 544         application_keypad_mode ();
 545 
 546     /* HACK:
 547      * Save sigwinch flag that will be reset in mc_refresh() called via update_panels().
 548      * There is some problem with screen redraw in ncurses-based mc in this situation.
 549      */
 550     was_sigwinch = tty_got_winch ();
 551     tty_flush_winch ();
 552 
 553 #ifdef ENABLE_SUBSHELL
 554     if (mc_global.tty.use_subshell)
 555     {
 556         if (mc_global.mc_run_mode == MC_RUN_FULL)
 557         {
 558             if (new_dir_vpath != NULL)
 559                 do_possible_cd (new_dir_vpath);
 560         }
 561         else if (new_dir_vpath != NULL && mc_chdir (new_dir_vpath) != -1)
 562             vfs_setup_cwd ();
 563     }
 564 
 565     vfs_path_free (new_dir_vpath, TRUE);
 566 #endif /* ENABLE_SUBSHELL */
 567 
 568     if (mc_global.mc_run_mode == MC_RUN_FULL)
 569     {
 570         update_panels (UP_OPTIMIZE, UP_KEEPSEL);
 571         update_xterm_title_path ();
 572         update_terminal_cwd ();
 573     }
 574 
 575     if (was_sigwinch != 0 || tty_got_winch ())
 576         dialog_change_screen_size ();
 577     else
 578         repaint_screen ();
 579 }
 580 
 581 /* --------------------------------------------------------------------------------------------- */
 582 
 583 /* event callback */
 584 gboolean
 585 execute_suspend (const gchar *event_group_name, const gchar *event_name,
     /* [previous][next][first][last][top][bottom][index][help]  */
 586                  gpointer init_data, gpointer data)
 587 {
 588     (void) event_group_name;
 589     (void) event_name;
 590     (void) init_data;
 591     (void) data;
 592 
 593     if (mc_global.mc_run_mode == MC_RUN_FULL)
 594         save_cwds_stat ();
 595     do_suspend_cmd ();
 596     if (mc_global.mc_run_mode == MC_RUN_FULL)
 597         update_panels (UP_OPTIMIZE, UP_KEEPSEL);
 598     do_refresh ();
 599 
 600     return TRUE;
 601 }
 602 
 603 /* --------------------------------------------------------------------------------------------- */
 604 
 605 /**
 606  * Execute command on a filename that can be on VFS.
 607  * Errors are reported to the user.
 608  */
 609 
 610 void
 611 execute_with_vfs_arg (const char *command, const vfs_path_t *filename_vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 612 {
 613     vfs_path_t *localcopy_vpath = NULL;
 614     const vfs_path_t *do_execute_vpath;
 615     time_t mtime;
 616 
 617     if (!execute_prepare_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime))
 618         return;
 619 
 620     do_execute_vpath = (localcopy_vpath == NULL) ? filename_vpath : localcopy_vpath;
 621 
 622     do_execute (command, vfs_path_get_last_path_str (do_execute_vpath), EXECUTE_INTERNAL);
 623 
 624     execute_cleanup_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime);
 625 }
 626 
 627 /* --------------------------------------------------------------------------------------------- */
 628 /**
 629  * Execute external editor or viewer.
 630  *
 631  * @param command editor/viewer to run
 632  * @param filename_vpath path for edit/view
 633  * @param start_line cursor will be placed at the 'start_line' position after opening file
 634  *        if start_line is 0 or negative, no start line will be passed to editor/viewer
 635  */
 636 
 637 void
 638 execute_external_editor_or_viewer (const char *command, const vfs_path_t *filename_vpath,
     /* [previous][next][first][last][top][bottom][index][help]  */
 639                                    long start_line)
 640 {
 641     vfs_path_t *localcopy_vpath = NULL;
 642     const vfs_path_t *do_execute_vpath;
 643     char *extern_cmd_options;
 644     time_t mtime = 0;
 645 
 646     if (!execute_prepare_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime))
 647         return;
 648 
 649     do_execute_vpath = (localcopy_vpath == NULL) ? filename_vpath : localcopy_vpath;
 650 
 651     extern_cmd_options =
 652         execute_get_external_cmd_opts_from_config (command, do_execute_vpath, start_line);
 653 
 654     if (extern_cmd_options != NULL)
 655     {
 656         char **argv_cmd_options;
 657         int argv_count;
 658 
 659         if (g_shell_parse_argv (extern_cmd_options, &argv_count, &argv_cmd_options, NULL))
 660         {
 661             do_executev (command, EXECUTE_INTERNAL, argv_cmd_options);
 662             g_strfreev (argv_cmd_options);
 663         }
 664         else
 665             do_executev (command, EXECUTE_INTERNAL, NULL);
 666 
 667         g_free (extern_cmd_options);
 668     }
 669 
 670     execute_cleanup_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime);
 671 }
 672 
 673 /* --------------------------------------------------------------------------------------------- */

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