/* *INDENT-OFF* */ END_TEST /* *INDENT-ON* */ /* --------------------------------------------------------------------------------------------- */ /* @Test */ /* *INDENT-OFF* */ START_TEST (test_mc_mkstemps) /* *INDENT-ON* */ { /* given */ vfs_path_t *pname_vpath = NULL; char *pname = NULL; char *begin_pname; int fd; /* when */ fd = mc_mkstemps (&pname_vpath, "mctest-", NULL); if (fd != -1) pname = vfs_path_to_str (pname_vpath); begin_pname = g_build_filename (mc_tmpdir (), "mctest-", NULL); /* then */ vfs_path_free (pname_vpath); close (fd); mctest_assert_int_ne (fd, -1); fail_unless (g_file_test (pname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR), "\nNo such file: %s\n", pname); unlink (pname); fail_unless (strncmp (pname, begin_pname, strlen (begin_pname)) == 0, "\nstart of %s should be equal to %s\n", pname, begin_pname); g_free (pname); }
/** POSIX version. The only version we support. */ static void OS_Setup (void) { const char *shell_env; const char *datadir_env; shell_env = getenv ("SHELL"); if ((shell_env == NULL) || (shell_env[0] == '\0')) { struct passwd *pwd; pwd = getpwuid (geteuid ()); if (pwd != NULL) mc_global.tty.shell = g_strdup (pwd->pw_shell); } else mc_global.tty.shell = g_strdup (shell_env); if ((mc_global.tty.shell == NULL) || (mc_global.tty.shell[0] == '\0')) { g_free (mc_global.tty.shell); mc_global.tty.shell = g_strdup ("/bin/sh"); } /* This is the directory, where MC was installed, on Unix this is DATADIR */ /* and can be overriden by the MC_DATADIR environment variable */ datadir_env = g_getenv ("MC_DATADIR"); if (datadir_env != NULL) mc_global.sysconfig_dir = g_strdup (datadir_env); else mc_global.sysconfig_dir = g_strdup (SYSCONFDIR); mc_global.share_data_dir = g_strdup (DATADIR); /* Set up temporary directory */ mc_tmpdir (); }
void init_subshell (void) { /* This must be remembered across calls to init_subshell() */ static char pty_name[BUF_SMALL]; char precmd[BUF_SMALL]; switch (check_sid ()) { case 1: mc_global.tty.use_subshell = FALSE; return; case 2: mc_global.tty.use_subshell = FALSE; mc_global.midnight_shutdown = TRUE; return; } /* Take the current (hopefully pristine) tty mode and make */ /* a raw mode based on it now, before we do anything else with it */ init_raw_mode (); if (mc_global.tty.subshell_pty == 0) { /* First time through */ /* Find out what type of shell we have */ if (strstr (mc_global.tty.shell, "/zsh") || getenv ("ZSH_VERSION")) subshell_type = ZSH; else if (strstr (mc_global.tty.shell, "/tcsh")) subshell_type = TCSH; else if (strstr (mc_global.tty.shell, "/csh")) subshell_type = TCSH; else if (strstr (mc_global.tty.shell, "/bash") || getenv ("BASH")) subshell_type = BASH; else if (strstr (mc_global.tty.shell, "/fish")) subshell_type = FISH; else { mc_global.tty.use_subshell = FALSE; return; } /* Open a pty for talking to the subshell */ /* FIXME: We may need to open a fresh pty each time on SVR4 */ mc_global.tty.subshell_pty = pty_open_master (pty_name); if (mc_global.tty.subshell_pty == -1) { fprintf (stderr, "Cannot open master side of pty: %s\r\n", unix_error_string (errno)); mc_global.tty.use_subshell = FALSE; return; } subshell_pty_slave = pty_open_slave (pty_name); if (subshell_pty_slave == -1) { fprintf (stderr, "Cannot open slave side of pty %s: %s\r\n", pty_name, unix_error_string (errno)); mc_global.tty.use_subshell = FALSE; return; } /* Create a pipe for receiving the subshell's CWD */ if (subshell_type == TCSH) { g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d", mc_tmpdir (), (int) getpid ()); if (mkfifo (tcsh_fifo, 0600) == -1) { fprintf (stderr, "mkfifo(%s) failed: %s\r\n", tcsh_fifo, unix_error_string (errno)); mc_global.tty.use_subshell = FALSE; return; } /* Opening the FIFO as O_RDONLY or O_WRONLY causes deadlock */ if ((subshell_pipe[READ] = open (tcsh_fifo, O_RDWR)) == -1 || (subshell_pipe[WRITE] = open (tcsh_fifo, O_RDWR)) == -1) { fprintf (stderr, _("Cannot open named pipe %s\n"), tcsh_fifo); perror (__FILE__ ": open"); mc_global.tty.use_subshell = FALSE; return; } } else /* subshell_type is BASH or ZSH */ if (pipe (subshell_pipe)) { perror (__FILE__ ": couldn't create pipe"); mc_global.tty.use_subshell = FALSE; return; } } /* Fork the subshell */ subshell_alive = TRUE; subshell_stopped = FALSE; subshell_pid = fork (); if (subshell_pid == -1) { fprintf (stderr, "Cannot spawn the subshell process: %s\r\n", unix_error_string (errno)); /* We exit here because, if the process table is full, the */ /* other method of running user commands won't work either */ exit (EXIT_FAILURE); } if (subshell_pid == 0) { /* We are in the child process */ init_subshell_child (pty_name); } /* Set up 'precmd' or equivalent for reading the subshell's CWD */ switch (subshell_type) { case BASH: g_snprintf (precmd, sizeof (precmd), " PROMPT_COMMAND='pwd>&%d;kill -STOP $$'\n", subshell_pipe[WRITE]); break; case ZSH: g_snprintf (precmd, sizeof (precmd), " precmd(){ pwd>&%d;kill -STOP $$ }\n", subshell_pipe[WRITE]); break; case TCSH: g_snprintf (precmd, sizeof (precmd), "set echo_style=both;" "alias precmd 'echo $cwd:q >>%s;kill -STOP $$'\n", tcsh_fifo); break; case FISH: g_snprintf (precmd, sizeof (precmd), "function fish_prompt ; pwd>&%d;kill -STOP %%self; end\n", subshell_pipe[WRITE]); break; } write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd)); /* Wait until the subshell has started up and processed the command */ subshell_state = RUNNING_COMMAND; tty_enable_interrupt_key (); if (!feed_subshell (QUIETLY, TRUE)) { mc_global.tty.use_subshell = FALSE; } tty_disable_interrupt_key (); if (!subshell_alive) mc_global.tty.use_subshell = FALSE; /* Subshell died instantly, so don't use it */ }
void init_subshell (void) { /* This must be remembered across calls to init_subshell() */ static char pty_name[BUF_SMALL]; /* Must be considerably longer than BUF_SMALL (128) to support fancy shell prompts */ char precmd[BUF_MEDIUM]; switch (check_sid ()) { case 1: mc_global.tty.use_subshell = FALSE; return; case 2: mc_global.tty.use_subshell = FALSE; mc_global.midnight_shutdown = TRUE; return; default: break; } /* Take the current (hopefully pristine) tty mode and make */ /* a raw mode based on it now, before we do anything else with it */ init_raw_mode (); if (mc_global.tty.subshell_pty == 0) { /* First time through */ if (mc_global.shell->type == SHELL_NONE) return; /* Open a pty for talking to the subshell */ /* FIXME: We may need to open a fresh pty each time on SVR4 */ mc_global.tty.subshell_pty = pty_open_master (pty_name); if (mc_global.tty.subshell_pty == -1) { fprintf (stderr, "Cannot open master side of pty: %s\r\n", unix_error_string (errno)); mc_global.tty.use_subshell = FALSE; return; } subshell_pty_slave = pty_open_slave (pty_name); if (subshell_pty_slave == -1) { fprintf (stderr, "Cannot open slave side of pty %s: %s\r\n", pty_name, unix_error_string (errno)); mc_global.tty.use_subshell = FALSE; return; } /* Create a pipe for receiving the subshell's CWD */ if (mc_global.shell->type == SHELL_TCSH) { g_snprintf (tcsh_fifo, sizeof (tcsh_fifo), "%s/mc.pipe.%d", mc_tmpdir (), (int) getpid ()); if (mkfifo (tcsh_fifo, 0600) == -1) { fprintf (stderr, "mkfifo(%s) failed: %s\r\n", tcsh_fifo, unix_error_string (errno)); mc_global.tty.use_subshell = FALSE; return; } /* Opening the FIFO as O_RDONLY or O_WRONLY causes deadlock */ if ((subshell_pipe[READ] = open (tcsh_fifo, O_RDWR)) == -1 || (subshell_pipe[WRITE] = open (tcsh_fifo, O_RDWR)) == -1) { fprintf (stderr, _("Cannot open named pipe %s\n"), tcsh_fifo); perror (__FILE__ ": open"); mc_global.tty.use_subshell = FALSE; return; } } else if (pipe (subshell_pipe)) /* subshell_type is BASH, ASH_BUSYBOX, DASH or ZSH */ { perror (__FILE__ ": couldn't create pipe"); mc_global.tty.use_subshell = FALSE; return; } } /* Fork the subshell */ subshell_alive = TRUE; subshell_stopped = FALSE; subshell_pid = fork (); if (subshell_pid == -1) { fprintf (stderr, "Cannot spawn the subshell process: %s\r\n", unix_error_string (errno)); /* We exit here because, if the process table is full, the */ /* other method of running user commands won't work either */ exit (EXIT_FAILURE); } if (subshell_pid == 0) { /* We are in the child process */ init_subshell_child (pty_name); } init_subshell_precmd (precmd, BUF_MEDIUM); write_all (mc_global.tty.subshell_pty, precmd, strlen (precmd)); /* Wait until the subshell has started up and processed the command */ subshell_state = RUNNING_COMMAND; tty_enable_interrupt_key (); if (!feed_subshell (QUIETLY, TRUE)) { mc_global.tty.use_subshell = FALSE; } tty_disable_interrupt_key (); if (!subshell_alive) mc_global.tty.use_subshell = FALSE; /* Subshell died instantly, so don't use it */ }
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); }
int mc_mkstemps (char **pname, const char *prefix, const char *suffix) { static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static unsigned long value; struct timeval tv; char *tmpbase; char *tmpname; char *XXXXXX; int count; if (strchr (prefix, PATH_SEP) == NULL) { /* Add prefix first to find the position of XXXXXX */ tmpbase = concat_dir_and_file (mc_tmpdir (), prefix); } else { tmpbase = g_strdup (prefix); } tmpname = g_strconcat (tmpbase, "XXXXXX", suffix, (char *) NULL); *pname = tmpname; XXXXXX = &tmpname[strlen (tmpbase)]; g_free (tmpbase); /* Get some more or less random data. */ gettimeofday (&tv, NULL); value += (tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); for (count = 0; count < TMP_MAX; ++count) { unsigned long v = value; int fd; /* Fill in the random bits. */ XXXXXX[0] = letters[v % 62]; v /= 62; XXXXXX[1] = letters[v % 62]; v /= 62; XXXXXX[2] = letters[v % 62]; v /= 62; XXXXXX[3] = letters[v % 62]; v /= 62; XXXXXX[4] = letters[v % 62]; v /= 62; XXXXXX[5] = letters[v % 62]; fd = open (tmpname, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR); if (fd >= 0) { /* Successfully created. */ return fd; } /* This is a random value. It is only necessary that the next TMP_MAX values generated by adding 7777 to VALUE are different with (module 2^32). */ value += 7777; } /* Unsuccessful. Free the filename. */ g_free (tmpname); *pname = NULL; return -1; }