Ejemplo n.º 1
0
/* *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);
}
Ejemplo n.º 2
0
Archivo: main.c Proyecto: Chainie/mc
/** 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 ();
}
Ejemplo n.º 3
0
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 */
}
Ejemplo n.º 4
0
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 */
}
Ejemplo n.º 5
0
Archivo: main.c Proyecto: V07D/mc
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);
    }
Ejemplo n.º 6
0
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;
}