int invoke_subshell (const char *command, int how, vfs_path_t ** new_dir_vpath) { char *pcwd; /* Make the MC terminal transparent */ tcsetattr (STDOUT_FILENO, TCSANOW, &raw_mode); /* Make the subshell change to MC's working directory */ if (new_dir_vpath != NULL) do_subshell_chdir (current_panel->cwd_vpath, TRUE, TRUE); if (command == NULL) /* The user has done "C-o" from MC */ { if (subshell_state == INACTIVE) { subshell_state = ACTIVE; /* FIXME: possibly take out this hack; the user can re-play it by hitting C-hyphen a few times! */ if (subshell_ready) write_all (mc_global.tty.subshell_pty, " \b", 2); /* Hack to make prompt reappear */ } } else /* MC has passed us a user command */ { if (how == QUIETLY) write_all (mc_global.tty.subshell_pty, " ", 1); /* FIXME: if command is long (>8KB ?) we go comma */ write_all (mc_global.tty.subshell_pty, command, strlen (command)); write_all (mc_global.tty.subshell_pty, "\n", 1); subshell_state = RUNNING_COMMAND; subshell_ready = FALSE; } feed_subshell (how, FALSE); { char *cwd_str; cwd_str = vfs_path_to_str (current_panel->cwd_vpath); pcwd = vfs_translate_path_n (cwd_str); g_free (cwd_str); } if (new_dir_vpath != NULL && subshell_alive && strcmp (subshell_cwd, pcwd)) *new_dir_vpath = vfs_path_from_str (subshell_cwd); /* Make MC change to the subshell's CWD */ g_free (pcwd); /* Restart the subshell if it has died by SIGHUP, SIGQUIT, etc. */ while (!subshell_alive && quit == 0 && mc_global.tty.use_subshell) init_subshell (); prompt_pos = 0; return quit; }
int main (int argc, char *argv[]) { GError *error = NULL; int exit_code = EXIT_FAILURE; /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */ (void) setlocale (LC_ALL, ""); (void) bindtextdomain ("mc", LOCALEDIR); (void) textdomain ("mc"); /* do this before args parsing */ str_init_strings (NULL); if (!mc_args_parse (&argc, &argv, "mc", &error)) { startup_exit_falure: fprintf (stderr, _("Failed to run:\n%s\n"), error->message); g_error_free (error); g_free (shell); startup_exit_ok: str_uninit_strings (); return exit_code; } /* do this before mc_args_show_info () to view paths in the --datadir-info output */ OS_Setup (); if (!g_path_is_absolute (mc_config_get_home_dir ())) { error = g_error_new (MC_ERROR, 0, "%s: %s", _("Home directory path is not absolute"), mc_config_get_home_dir ()); mc_event_deinit (NULL); goto startup_exit_falure; } if (!mc_args_show_info ()) { exit_code = EXIT_SUCCESS; goto startup_exit_ok; } if (!events_init (&error)) goto startup_exit_falure; mc_config_init_config_paths (&error); if (error == NULL && mc_config_deprecated_dir_present ()) mc_config_migrate_from_old_place (&error); if (error != NULL) { mc_event_deinit (NULL); goto startup_exit_falure; } vfs_init (); vfs_plugins_init (); vfs_setup_work_dir (); /* do this after vfs initialization due to mc_setctl() call in mc_setup_by_args() */ if (!mc_setup_by_args (argc, argv, &error)) { vfs_shut (); mc_event_deinit (NULL); goto startup_exit_falure; } /* check terminal type * $TEMR must be set and not empty * mc_global.tty.xterm_flag is used in init_key() and tty_init() * Do this after mc_args_handle() where mc_args__force_xterm is set up. */ mc_global.tty.xterm_flag = tty_check_term (mc_args__force_xterm); /* NOTE: This has to be called before tty_init or whatever routine calls any define_sequence */ init_key (); /* Must be done before installing the SIGCHLD handler [[FIXME]] */ handle_console (CONSOLE_INIT); #ifdef HAVE_SUBSHELL_SUPPORT /* Don't use subshell when invoked as viewer or editor */ if (mc_global.mc_run_mode != MC_RUN_FULL) mc_global.tty.use_subshell = FALSE; if (mc_global.tty.use_subshell) subshell_get_console_attributes (); #endif /* HAVE_SUBSHELL_SUPPORT */ /* Install the SIGCHLD handler; must be done before init_subshell() */ init_sigchld (); /* We need this, since ncurses endwin () doesn't restore the signals */ save_stop_handler (); /* Must be done before init_subshell, to set up the terminal size: */ /* FIXME: Should be removed and LINES and COLS computed on subshell */ tty_init (!mc_args__nomouse, mc_global.tty.xterm_flag); load_setup (); /* start check mc_global.display_codepage and mc_global.source_codepage */ check_codeset (); /* Removing this from the X code let's us type C-c */ load_key_defs (); load_keymap_defs (!mc_args__nokeymap); macros_list = g_array_new (TRUE, FALSE, sizeof (macros_t)); tty_init_colors (mc_global.tty.disable_colors, mc_args__force_colors); mc_skin_init (&error); if (error != NULL) { message (D_ERROR, _("Warning"), "%s", error->message); g_error_free (error); error = NULL; } mc_filehighlight = mc_fhl_new (TRUE); dlg_set_default_colors (); #ifdef HAVE_SUBSHELL_SUPPORT /* Done here to ensure that the subshell doesn't */ /* inherit the file descriptors opened below, etc */ if (mc_global.tty.use_subshell) init_subshell (); #endif /* HAVE_SUBSHELL_SUPPORT */ /* Also done after init_subshell, to save any shell init file messages */ if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_SAVE); if (mc_global.tty.alternate_plus_minus) application_keypad_mode (); #ifdef HAVE_SUBSHELL_SUPPORT if (mc_global.tty.use_subshell) { mc_prompt = strip_ctrl_codes (subshell_prompt); if (mc_prompt == NULL) mc_prompt = (geteuid () == 0) ? "# " : "$ "; } else #endif /* HAVE_SUBSHELL_SUPPORT */ mc_prompt = (geteuid () == 0) ? "# " : "$ "; /* Program main loop */ if (mc_global.midnight_shutdown) exit_code = EXIT_SUCCESS; else exit_code = do_nc ()? EXIT_SUCCESS : EXIT_FAILURE; /* Save the tree store */ (void) tree_store_save (); free_keymap_defs (); /* Virtual File System shutdown */ vfs_shut (); flush_extension_file (); /* does only free memory */ mc_fhl_free (&mc_filehighlight); mc_skin_deinit (); tty_colors_done (); tty_shutdown (); done_setup (); if (mc_global.tty.console_flag != '\0' && (quit & SUBSHELL_EXIT) == 0) handle_console (CONSOLE_RESTORE); if (mc_global.tty.alternate_plus_minus) numeric_keypad_mode (); (void) signal (SIGCHLD, SIG_DFL); /* Disable the SIGCHLD handler */ if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_DONE); if (mc_global.mc_run_mode == MC_RUN_FULL && mc_args__last_wd_file != NULL && last_wd_string != NULL && !print_last_revert) { int last_wd_fd; last_wd_fd = open (mc_args__last_wd_file, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR); if (last_wd_fd != -1) { ssize_t ret1; int ret2; ret1 = write (last_wd_fd, last_wd_string, strlen (last_wd_string)); ret2 = close (last_wd_fd); } } g_free (last_wd_string); g_free (shell); done_key (); if (macros_list != NULL) { guint i; macros_t *macros; for (i = 0; i < macros_list->len; i++) { macros = &g_array_index (macros_list, struct macros_t, i); if (macros != NULL && macros->macro != NULL) (void) g_array_free (macros->macro, FALSE); } (void) g_array_free (macros_list, TRUE); }
int main (int argc, char *argv[]) { GError *mcerror = NULL; gboolean config_migrated = FALSE; char *config_migrate_msg; int exit_code = EXIT_FAILURE; mc_global.timer = mc_timer_new (); /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */ #ifdef HAVE_SETLOCALE (void) setlocale (LC_ALL, ""); #endif (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); /* do this before args parsing */ str_init_strings (NULL); if (!mc_args_parse (&argc, &argv, "mc", &mcerror)) { startup_exit_falure: fprintf (stderr, _("Failed to run:\n%s\n"), mcerror->message); g_error_free (mcerror); g_free (mc_global.tty.shell); startup_exit_ok: str_uninit_strings (); mc_timer_destroy (mc_global.timer); return exit_code; } /* do this before mc_args_show_info () to view paths in the --datadir-info output */ OS_Setup (); if (!g_path_is_absolute (mc_config_get_home_dir ())) { mc_propagate_error (&mcerror, 0, "%s: %s", _("Home directory path is not absolute"), mc_config_get_home_dir ()); mc_event_deinit (NULL); goto startup_exit_falure; } if (!mc_args_show_info ()) { exit_code = EXIT_SUCCESS; goto startup_exit_ok; } if (!events_init (&mcerror)) goto startup_exit_falure; mc_config_init_config_paths (&mcerror); config_migrated = mc_config_migrate_from_old_place (&mcerror, &config_migrate_msg); if (mcerror != NULL) { mc_event_deinit (NULL); goto startup_exit_falure; } vfs_init (); vfs_plugins_init (); load_setup (); /* Must be done after load_setup because depends on mc_global.vfs.cd_symlinks */ vfs_setup_work_dir (); /* Resolve the other_dir panel option. Must be done after vfs_setup_work_dir */ { char *buffer; vfs_path_t *vpath; buffer = mc_config_get_string (mc_panels_config, "Dirs", "other_dir", "."); vpath = vfs_path_from_str (buffer); if (vfs_file_is_local (vpath)) saved_other_dir = buffer; else g_free (buffer); vfs_path_free (vpath); } /* Set up temporary directory after VFS initialization */ mc_tmpdir (); /* do this after vfs initialization and vfs working directory setup due to mc_setctl() and mcedit_arg_vpath_new() calls in mc_setup_by_args() */ if (!mc_setup_by_args (argc, argv, &mcerror)) { vfs_shut (); done_setup (); g_free (saved_other_dir); mc_event_deinit (NULL); goto startup_exit_falure; } /* check terminal type * $TEMR must be set and not empty * mc_global.tty.xterm_flag is used in init_key() and tty_init() * Do this after mc_args_handle() where mc_args__force_xterm is set up. */ mc_global.tty.xterm_flag = tty_check_term (mc_args__force_xterm); /* NOTE: This has to be called before tty_init or whatever routine calls any define_sequence */ init_key (); /* Must be done before installing the SIGCHLD handler [[FIXME]] */ handle_console (CONSOLE_INIT); #ifdef ENABLE_SUBSHELL /* Don't use subshell when invoked as viewer or editor */ if (mc_global.mc_run_mode != MC_RUN_FULL) mc_global.tty.use_subshell = FALSE; if (mc_global.tty.use_subshell) subshell_get_console_attributes (); #endif /* ENABLE_SUBSHELL */ /* Install the SIGCHLD handler; must be done before init_subshell() */ init_sigchld (); /* We need this, since ncurses endwin () doesn't restore the signals */ save_stop_handler (); /* Must be done before init_subshell, to set up the terminal size: */ /* FIXME: Should be removed and LINES and COLS computed on subshell */ tty_init (!mc_args__nomouse, mc_global.tty.xterm_flag); /* start check mc_global.display_codepage and mc_global.source_codepage */ check_codeset (); /* Removing this from the X code let's us type C-c */ load_key_defs (); load_keymap_defs (!mc_args__nokeymap); macros_list = g_array_new (TRUE, FALSE, sizeof (macros_t)); tty_init_colors (mc_global.tty.disable_colors, mc_args__force_colors); mc_skin_init (NULL, &mcerror); dlg_set_default_colors (); input_set_default_colors (); if (mc_global.mc_run_mode == MC_RUN_FULL) command_set_default_colors (); mc_error_message (&mcerror); #ifdef ENABLE_SUBSHELL /* Done here to ensure that the subshell doesn't */ /* inherit the file descriptors opened below, etc */ if (mc_global.tty.use_subshell) init_subshell (); #endif /* ENABLE_SUBSHELL */ /* Also done after init_subshell, to save any shell init file messages */ if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_SAVE); if (mc_global.tty.alternate_plus_minus) application_keypad_mode (); /* Done after subshell initialization to allow select and paste text by mouse w/o Shift button in subshell in the native console */ init_mouse (); /* Done after do_enter_ca_mode (tty_init) because in VTE bracketed mode is separate for the normal and alternate screens */ enable_bracketed_paste (); /* subshell_prompt is NULL here */ mc_prompt = (geteuid () == 0) ? "# " : "$ "; if (config_migrated) { message (D_ERROR, _("Warning"), "%s", config_migrate_msg); g_free (config_migrate_msg); } /* Program main loop */ if (mc_global.midnight_shutdown) exit_code = EXIT_SUCCESS; else exit_code = do_nc ()? EXIT_SUCCESS : EXIT_FAILURE; /* Save the tree store */ (void) tree_store_save (); free_keymap_defs (); /* Virtual File System shutdown */ vfs_shut (); flush_extension_file (); /* does only free memory */ mc_skin_deinit (); tty_colors_done (); tty_shutdown (); done_setup (); if (mc_global.tty.console_flag != '\0' && (quit & SUBSHELL_EXIT) == 0) handle_console (CONSOLE_RESTORE); if (mc_global.tty.alternate_plus_minus) numeric_keypad_mode (); (void) signal (SIGCHLD, SIG_DFL); /* Disable the SIGCHLD handler */ if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_DONE); if (mc_global.mc_run_mode == MC_RUN_FULL && mc_args__last_wd_file != NULL && last_wd_string != NULL && !print_last_revert) { int last_wd_fd; last_wd_fd = open (mc_args__last_wd_file, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR); if (last_wd_fd != -1) { ssize_t ret1; int ret2; ret1 = write (last_wd_fd, last_wd_string, strlen (last_wd_string)); ret2 = close (last_wd_fd); (void) ret1; (void) ret2; } } g_free (last_wd_string); g_free (mc_global.tty.shell); done_key (); if (macros_list != NULL) { guint i; for (i = 0; i < macros_list->len; i++) { macros_t *macros; macros = &g_array_index (macros_list, struct macros_t, i); if (macros != NULL && macros->macro != NULL) (void) g_array_free (macros->macro, FALSE); } (void) g_array_free (macros_list, TRUE); }
static cb_ret_t enter (WInput * lc_cmdline) { char *cmd = lc_cmdline->buffer; if (!command_prompt) return MSG_HANDLED; /* Any initial whitespace should be removed at this point */ while (*cmd == ' ' || *cmd == '\t' || *cmd == '\n') cmd++; if (!*cmd) return MSG_HANDLED; if (strncmp (cmd, "cd ", 3) == 0 || strcmp (cmd, "cd") == 0) { do_cd_command (cmd); input_clean (lc_cmdline); return MSG_HANDLED; } else if (strcmp (cmd, "exit") == 0) { input_assign_text (lc_cmdline, ""); if (!quiet_quit_cmd ()) return MSG_NOT_HANDLED; } else { GString *command; size_t i; if (!vfs_current_is_local ()) { message (D_ERROR, MSG_ERROR, _("Cannot execute commands on non-local filesystems")); return MSG_NOT_HANDLED; } #ifdef ENABLE_SUBSHELL /* Check this early before we clean command line * (will be checked again by shell_execute) */ if (mc_global.tty.use_subshell && subshell_state != INACTIVE) { message (D_ERROR, MSG_ERROR, _("The shell is already running a command")); return MSG_NOT_HANDLED; } #endif command = g_string_sized_new (32); for (i = 0; cmd[i] != '\0'; i++) { if (cmd[i] != '%') g_string_append_c (command, cmd[i]); else { char *s; s = expand_format (NULL, cmd[++i], TRUE); g_string_append (command, s); g_free (s); } } input_clean (lc_cmdline); shell_execute (command->str, 0); g_string_free (command, TRUE); #ifdef ENABLE_SUBSHELL if ((quit & SUBSHELL_EXIT) != 0) { if (quiet_quit_cmd ()) return MSG_HANDLED; quit = 0; /* restart subshell */ if (mc_global.tty.use_subshell) init_subshell (); } if (mc_global.tty.use_subshell) do_load_prompt (); #endif } return MSG_HANDLED; }
void toggle_panels (void) { #ifdef ENABLE_SUBSHELL vfs_path_t *new_dir_vpath = NULL; #endif /* ENABLE_SUBSHELL */ SIG_ATOMIC_VOLATILE_T was_sigwinch = 0; channels_down (); disable_mouse (); disable_bracketed_paste (); if (clear_before_exec) clr_scr (); if (mc_global.tty.alternate_plus_minus) numeric_keypad_mode (); #ifndef HAVE_SLANG /* With slang we don't want any of this, since there * is no raw_mode supported */ tty_reset_shell_mode (); #endif /* !HAVE_SLANG */ tty_noecho (); tty_keypad (FALSE); tty_reset_screen (); do_exit_ca_mode (); tty_raw_mode (); if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_RESTORE); #ifdef ENABLE_SUBSHELL if (mc_global.tty.use_subshell) { vfs_path_t **new_dir_p; new_dir_p = vfs_current_is_local ()? &new_dir_vpath : NULL; invoke_subshell (NULL, VISIBLY, new_dir_p); } else #endif /* ENABLE_SUBSHELL */ { if (output_starts_shell) { fprintf (stderr, _("Type 'exit' to return to the Midnight Commander")); fprintf (stderr, "\n\r\n\r"); my_system (EXECUTE_INTERNAL, mc_global.tty.shell, NULL); } else get_key_code (0); } if (mc_global.tty.console_flag != '\0') handle_console (CONSOLE_SAVE); do_enter_ca_mode (); tty_reset_prog_mode (); tty_keypad (TRUE); /* Prevent screen flash when user did 'exit' or 'logout' within subshell */ if ((quit & SUBSHELL_EXIT) != 0) { /* User did 'exit' or 'logout': quit MC */ if (quiet_quit_cmd ()) return; quit = 0; #ifdef ENABLE_SUBSHELL /* restart subshell */ if (mc_global.tty.use_subshell) init_subshell (); #endif /* ENABLE_SUBSHELL */ } enable_mouse (); enable_bracketed_paste (); channels_up (); if (mc_global.tty.alternate_plus_minus) application_keypad_mode (); /* HACK: * Save sigwinch flag that will be reset in mc_refresh() called via update_panels(). * There is some problem with screen redraw in ncurses-based mc in this situation. */ was_sigwinch = mc_global.tty.winch_flag; mc_global.tty.winch_flag = 0; #ifdef ENABLE_SUBSHELL if (mc_global.tty.use_subshell) { do_load_prompt (); if (new_dir_vpath != NULL) do_possible_cd (new_dir_vpath); if (mc_global.tty.console_flag != '\0' && output_lines) show_console_contents (output_start_y, LINES - mc_global.keybar_visible - output_lines - 1, LINES - mc_global.keybar_visible - 1); } vfs_path_free (new_dir_vpath); #endif /* ENABLE_SUBSHELL */ if (mc_global.mc_run_mode == MC_RUN_FULL) { update_panels (UP_OPTIMIZE, UP_KEEPSEL); update_xterm_title_path (); } if (was_sigwinch != 0 || mc_global.tty.winch_flag != 0) dialog_change_screen_size (); else repaint_screen (); }