Пример #1
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 */
}
Пример #2
0
static int
sftpfs_open_socket (struct vfs_s_super *super, GError ** error)
{
    struct addrinfo hints, *res = NULL, *curr_res;
    int my_socket = 0;
    char port[BUF_TINY];
    int e;

    if (super->path_element->host == NULL || *super->path_element->host == '\0')
    {
        g_set_error (error, MC_ERROR, -1, _("sftp: Invalid host name."));
        return -1;
    }

    sprintf (port, "%hu", (unsigned short) super->path_element->port);
    if (port == NULL)
    {
        g_set_error (error, MC_ERROR, -1, _("sftp: Invalid port value."));
        return -1;
    }

    tty_enable_interrupt_key ();        /* clear the interrupt flag */

    memset (&hints, 0, sizeof (struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

#ifdef AI_ADDRCONFIG
    /* By default, only look up addresses using address types for
     * which a local interface is configured (i.e. no IPv6 if no IPv6
     * interfaces, likewise for IPv4 (see RFC 3493 for details). */
    hints.ai_flags = AI_ADDRCONFIG;
#endif

    e = getaddrinfo (super->path_element->host, port, &hints, &res);

#ifdef AI_ADDRCONFIG
    if (e == EAI_BADFLAGS)
    {
        /* Retry with no flags if AI_ADDRCONFIG was rejected. */
        hints.ai_flags = 0;
        e = getaddrinfo (super->path_element->host, port, &hints, &res);
    }
#endif

    if (e != 0)
    {
        g_set_error (error, MC_ERROR, -1, _("sftp: %s"), gai_strerror (e));
        my_socket = -1;
        goto ret;
    }

    for (curr_res = res; curr_res != NULL; curr_res = curr_res->ai_next)
    {
        my_socket = socket (curr_res->ai_family, curr_res->ai_socktype, curr_res->ai_protocol);

        if (my_socket < 0)
        {
            if (curr_res->ai_next != NULL)
                continue;

            vfs_print_message (_("sftp: %s"), unix_error_string (errno));
            my_socket = -1;
            goto ret;
        }

        vfs_print_message (_("sftp: making connection to %s"), super->path_element->host);

        if (connect (my_socket, curr_res->ai_addr, curr_res->ai_addrlen) >= 0)
            break;

        close (my_socket);

        if (errno == EINTR && tty_got_interrupt ())
            g_set_error (error, MC_ERROR, -1, _("sftp: connection interrupted by user"));
        else if (res->ai_next == NULL)
            g_set_error (error, MC_ERROR, -1, _("sftp: connection to server failed: %s"),
                         unix_error_string (errno));
        else
            continue;

        my_socket = -1;
        break;
    }

  ret:
    if (res != NULL)
        freeaddrinfo (res);
    tty_disable_interrupt_key ();
    return my_socket;
}
Пример #3
0
void
mcview_ccache_lookup (mcview_t * view, coord_cache_entry_t * coord, enum ccache_type lookup_what)
{
    size_t i;
    coord_cache_t *cache;
    coord_cache_entry_t current, next, entry;
    enum ccache_type sorter;
    off_t limit;
    cmp_func_t cmp_func;

    enum
    {
        NROFF_START,
        NROFF_BACKSPACE,
        NROFF_CONTINUATION
    } nroff_state;

    if (view->coord_cache == NULL)
        view->coord_cache = coord_cache_new ();

    cache = view->coord_cache;

    if (cache->size == 0)
    {
        current.cc_offset = 0;
        current.cc_line = 0;
        current.cc_column = 0;
        current.cc_nroff_column = 0;
        mcview_ccache_add_entry (cache, 0, &current);
    }

    sorter = (lookup_what == CCACHE_OFFSET) ? CCACHE_LINECOL : CCACHE_OFFSET;

    if (sorter == CCACHE_OFFSET)
        cmp_func = mcview_coord_cache_entry_less_offset;
    else if (view->text_nroff_mode)
        cmp_func = mcview_coord_cache_entry_less_nroff;
    else
        cmp_func = mcview_coord_cache_entry_less_plain;


    tty_enable_interrupt_key ();

retry:
    /* find the two neighbor entries in the cache */
    i = mcview_ccache_find (view, coord, cmp_func);
    /* now i points to the lower neighbor in the cache */

    current = *cache->cache[i];
    if (i + 1 < view->coord_cache->size)
        limit = cache->cache[i + 1]->cc_offset;
    else
        limit = current.cc_offset + VIEW_COORD_CACHE_GRANUL;

    entry = current;
    nroff_state = NROFF_START;
    for (; current.cc_offset < limit; current = next)
    {
        int c, nextc;

        if (!mcview_get_byte (view, current.cc_offset, &c))
            break;

        if (!cmp_func (&current, coord))
        {
            if (lookup_what == CCACHE_OFFSET && view->text_nroff_mode && nroff_state != NROFF_START)
            {
                /* don't break here */
            }
            else
            {
                break;
            }
        }

        /* Provide useful default values for ''next'' */
        next.cc_offset = current.cc_offset + 1;
        next.cc_line = current.cc_line;
        next.cc_column = current.cc_column + 1;
        next.cc_nroff_column = current.cc_nroff_column + 1;

        /* and override some of them as necessary. */
        if (c == '\r')
        {
            mcview_get_byte_indexed (view, current.cc_offset, 1, &nextc);

            /* Ignore '\r' if it is followed by '\r' or '\n'. If it is
             * followed by anything else, it is a Mac line ending and
             * produces a line break.
             */
            if (nextc == '\r' || nextc == '\n')
            {
                next.cc_column = current.cc_column;
                next.cc_nroff_column = current.cc_nroff_column;
            }
            else
            {
                next.cc_line = current.cc_line + 1;
                next.cc_column = 0;
                next.cc_nroff_column = 0;
            }

        }
        else if (nroff_state == NROFF_BACKSPACE)
        {
            next.cc_nroff_column = current.cc_nroff_column - 1;

        }
        else if (c == '\t')
        {
            next.cc_column = mcview_offset_rounddown (current.cc_column, 8) + 8;
            next.cc_nroff_column = mcview_offset_rounddown (current.cc_nroff_column, 8) + 8;

        }
        else if (c == '\n')
        {
            next.cc_line = current.cc_line + 1;
            next.cc_column = 0;
            next.cc_nroff_column = 0;

        }
        else
        {
            /* Use all default values from above */
        }

        switch (nroff_state)
        {
        case NROFF_START:
        case NROFF_CONTINUATION:
            nroff_state = mcview_is_nroff_sequence (view, current.cc_offset)
                          ? NROFF_BACKSPACE : NROFF_START;
            break;
        case NROFF_BACKSPACE:
            nroff_state = NROFF_CONTINUATION;
            break;
        }

        /* Cache entries must guarantee that for each i < j,
         * line[i] <= line[j] and column[i] < column[j]. In the case of
         * nroff sequences and '\r' characters, this is not guaranteed,
         * so we cannot save them. */
        if (nroff_state == NROFF_START && c != '\r')
            entry = next;
    }

    if (i + 1 == cache->size && entry.cc_offset != cache->cache[i]->cc_offset)
    {
        mcview_ccache_add_entry (cache, cache->size, &entry);

        if (!tty_got_interrupt ())
            goto retry;
    }

    tty_disable_interrupt_key ();

    if (lookup_what == CCACHE_OFFSET)
    {
        coord->cc_offset = current.cc_offset;
    }
    else
    {
        coord->cc_line = current.cc_line;
        coord->cc_column = current.cc_column;
        coord->cc_nroff_column = current.cc_nroff_column;
    }
}
Пример #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 */
}
Пример #5
0
void
mcview_do_search (mcview_t * view)
{
    off_t search_start = 0;
    gboolean isFound = FALSE;
    gboolean need_search_again = TRUE;

    Dlg_head *d = NULL;

    size_t match_len;

    if (verbose)
    {
        d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
        tty_refresh ();
    }

    /*for avoid infinite search loop we need to increase or decrease start offset of search */

    if (view->search_start != 0)
    {
        if (!view->text_nroff_mode)
            search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0);
        else
        {
            if (mcview_search_options.backwards)
            {
                mcview_nroff_t *nroff;
                nroff = mcview_nroff_seq_new_num (view, view->search_start);
                if (mcview_nroff_seq_prev (nroff) != -1)
                    search_start =
                        -(mcview__get_nroff_real_len (view, nroff->index - 1, 2) +
                          nroff->char_width + 1);
                else
                    search_start = -2;

                mcview_nroff_seq_free (&nroff);
            }
            else
            {
                search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2);
            }
            search_start += view->search_start;
        }
    }

    if (mcview_search_options.backwards && (int) search_start < 0)
        search_start = 0;

    /* Compute the percent steps */
    mcview_search_update_steps (view);
    view->update_activate = 0;

    tty_enable_interrupt_key ();

    do
    {
        off_t growbufsize;

        if (view->growbuf_in_use)
            growbufsize = mcview_growbuf_filesize (view);
        else
            growbufsize = view->search->original_len;

        if (mcview_find (view, search_start, &match_len))
        {
            mcview_search_show_result (view, &d, match_len);
            need_search_again = FALSE;
            isFound = TRUE;
            break;
        }

        if (view->search->error_str == NULL)
            break;

        search_start = growbufsize - view->search->original_len;
        if (search_start <= 0)
        {
            search_start = 0;
            break;
        }
    }
    while (mcview_may_still_grow (view));

    if (view->search_start != 0 && !isFound && need_search_again
        && !mcview_search_options.backwards)
    {
        int result;

        mcview_update (view);

        result =
            query_dialog (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"),
                          _("&No"));

        if (result != 0)
            isFound = TRUE;
        else
            search_start = 0;
    }

    if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len))
    {
        mcview_search_show_result (view, &d, match_len);
        isFound = TRUE;
    }

    tty_disable_interrupt_key ();

    if (verbose)
    {
        dlg_run_done (d);
        destroy_dlg (d);
    }

    if (!isFound && view->search->error_str != NULL)
        message (D_NORMAL, _("Search"), "%s", view->search->error_str);

    view->dirty++;
    mcview_update (view);
}