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 */ }
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; }
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, ¤t); } 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 (¤t, 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; } }
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 */ }
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); }