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; }
/** If it actually changed the directory it returns true */ void do_subshell_chdir (const vfs_path_t * vpath, gboolean update_prompt) { char *pcwd; pcwd = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_RECODE); if (!(subshell_state == INACTIVE && strcmp (subshell_cwd, pcwd) != 0)) { /* We have to repaint the subshell prompt if we read it from * the main program. Please note that in the code after this * if, the cd command that is sent will make the subshell * repaint the prompt, so we don't have to paint it. */ if (update_prompt) do_update_prompt (); g_free (pcwd); return; } /* The initial space keeps this out of the command history (in bash because we set "HISTCONTROL=ignorespace") */ write_all (mc_global.tty.subshell_pty, " cd ", 4); if (vpath != NULL) { char *translate; translate = vfs_translate_path_n (vfs_path_as_str (vpath)); if (translate != NULL) { GString *temp; temp = subshell_name_quote (translate); write_all (mc_global.tty.subshell_pty, temp->str, temp->len); g_string_free (temp, TRUE); g_free (translate); } else { write_all (mc_global.tty.subshell_pty, ".", 1); } } else { write_all (mc_global.tty.subshell_pty, "/", 1); } write_all (mc_global.tty.subshell_pty, "\n", 1); subshell_state = RUNNING_COMMAND; feed_subshell (QUIETLY, FALSE); if (subshell_alive) { int bPathNotEq = strcmp (subshell_cwd, pcwd); if (bPathNotEq && subshell_type == TCSH) { char rp_subshell_cwd[PATH_MAX]; char rp_current_panel_cwd[PATH_MAX]; char *p_subshell_cwd = mc_realpath (subshell_cwd, rp_subshell_cwd); char *p_current_panel_cwd = mc_realpath (pcwd, rp_current_panel_cwd); if (p_subshell_cwd == NULL) p_subshell_cwd = subshell_cwd; if (p_current_panel_cwd == NULL) p_current_panel_cwd = pcwd; bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd); } if (bPathNotEq && !DIR_IS_DOT (pcwd)) { char *cwd; cwd = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_STRIP_PASSWORD); vfs_print_message (_("Warning: Cannot change to %s.\n"), cwd); g_free (cwd); } } update_subshell_prompt = FALSE; g_free (pcwd); /* Make sure that MC never stores the CWD in a silly format */ /* like /usr////lib/../bin, or the strcmp() above will fail */ }
/** If it actually changed the directory it returns true */ void do_subshell_chdir (const char *directory, gboolean update_prompt, gboolean reset_prompt) { char *pcwd; char *temp; char *translate; pcwd = vfs_translate_path_n (current_panel->cwd); if (!(subshell_state == INACTIVE && strcmp (subshell_cwd, pcwd) != 0)) { /* We have to repaint the subshell prompt if we read it from * the main program. Please note that in the code after this * if, the cd command that is sent will make the subshell * repaint the prompt, so we don't have to paint it. */ if (update_prompt) do_update_prompt (); g_free (pcwd); return; } /* The initial space keeps this out of the command history (in bash because we set "HISTCONTROL=ignorespace") */ write_all (mc_global.tty.subshell_pty, " cd ", 4); if (*directory) { translate = vfs_translate_path_n (directory); if (translate) { temp = subshell_name_quote (translate); if (temp) { write_all (mc_global.tty.subshell_pty, temp, strlen (temp)); g_free (temp); } else { /* Should not happen unless the directory name is so long that we don't have memory to quote it. */ write_all (mc_global.tty.subshell_pty, ".", 1); } g_free (translate); } else { write_all (mc_global.tty.subshell_pty, ".", 1); } } else { write_all (mc_global.tty.subshell_pty, "/", 1); } write_all (mc_global.tty.subshell_pty, "\n", 1); subshell_state = RUNNING_COMMAND; feed_subshell (QUIETLY, FALSE); if (subshell_alive) { int bPathNotEq = strcmp (subshell_cwd, pcwd); if (bPathNotEq && subshell_type == TCSH) { char rp_subshell_cwd[PATH_MAX]; char rp_current_panel_cwd[PATH_MAX]; char *p_subshell_cwd = mc_realpath (subshell_cwd, rp_subshell_cwd); char *p_current_panel_cwd = mc_realpath (pcwd, rp_current_panel_cwd); if (p_subshell_cwd == NULL) p_subshell_cwd = subshell_cwd; if (p_current_panel_cwd == NULL) p_current_panel_cwd = pcwd; bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd); } if (bPathNotEq && strcmp (pcwd, ".")) { char *cwd = strip_password (g_strdup (pcwd), 1); fprintf (stderr, _("Warning: Cannot change to %s.\n"), cwd); g_free (cwd); } } if (reset_prompt) prompt_pos = 0; update_subshell_prompt = FALSE; g_free (pcwd); /* Make sure that MC never stores the CWD in a silly format */ /* like /usr////lib/../bin, or the strcmp() above will fail */ }