gboolean mcview_load_command_output (WView * view, const char *command) { mc_pipe_t *p; GError *error = NULL; mcview_close_datasource (view); p = mc_popen (command, &error); if (p == NULL) { mcview_display (view); mcview_show_error (view, error->message); g_error_free (error); return FALSE; } /* Check if filter produced any output */ mcview_set_datasource_stdio_pipe (view, p); if (!mcview_get_byte (view, 0, NULL)) { mcview_close_datasource (view); mcview_display (view); return FALSE; } return TRUE; }
static void mcview_hook (void *v) { mcview_t *view = (mcview_t *) v; WPanel *panel; /* If the user is busy typing, wait until he finishes to update the screen */ if (!is_idle ()) { if (!hook_present (idle_hook, mcview_hook)) add_hook (&idle_hook, mcview_hook, v); return; } delete_hook (&idle_hook, mcview_hook); if (get_current_type () == view_listing) panel = current_panel; else if (get_other_type () == view_listing) panel = other_panel; else return; mcview_done (view); mcview_init (view); mcview_load (view, 0, panel->dir.list[panel->selected].fname, 0, 0, 0); mcview_display (view); }
gboolean mcview_load_command_output (mcview_t * view, const char *command) { FILE *fp; mcview_close_datasource (view); open_error_pipe (); fp = popen (command, "r"); if (fp == NULL) { /* Avoid two messages. Message from stderr has priority. */ mcview_display (view); if (!close_error_pipe (mcview_is_in_panel (view) ? -1 : D_ERROR, NULL)) mcview_show_error (view, _("Cannot spawn child process")); return FALSE; } /* First, check if filter produced any output */ mcview_set_datasource_stdio_pipe (view, fp); if (!mcview_get_byte (view, 0, NULL)) { mcview_close_datasource (view); /* Avoid two messages. Message from stderr has priority. */ mcview_display (view); if (!close_error_pipe (mcview_is_in_panel (view) ? -1 : D_ERROR, NULL)) mcview_show_error (view, _("Empty output from child filter")); return FALSE; } else { /* * At least something was read correctly. Close stderr and let * program die if it will try to write something there. * * Ideally stderr should be read asynchronously to prevent programs * from blocking (poll/select multiplexor). */ close_error_pipe (D_NORMAL, NULL); } return TRUE; }
void mcview_update (mcview_t * view) { static int dirt_limit = 1; if (view->dpy_bbar_dirty) { view->dpy_bbar_dirty = FALSE; mcview_set_buttonbar (view); buttonbar_redraw (find_buttonbar (view->widget.owner)); } if (view->dirty > dirt_limit) { /* Too many updates skipped -> force a update */ mcview_display (view); view->dirty = 0; /* Raise the update skipping limit */ dirt_limit++; if (dirt_limit > mcview_max_dirt_limit) dirt_limit = mcview_max_dirt_limit; } else if (view->dirty > 0) { if (is_idle ()) { /* We have time to update the screen properly */ mcview_display (view); view->dirty = 0; if (dirt_limit > 1) dirt_limit--; } else { /* We are busy -> skipping full update, only the status line is updated */ mcview_display_status (view); } /* Here we had a refresh, if fast scrolling does not work restore the refresh, although this should not happen */ } }
void mcview_close_datasource (mcview_t * view) { switch (view->datasource) { case DS_NONE: break; case DS_STDIO_PIPE: if (view->ds_stdio_pipe != NULL) { (void) pclose (view->ds_stdio_pipe); mcview_display (view); close_error_pipe (D_NORMAL, NULL); view->ds_stdio_pipe = NULL; } mcview_growbuf_free (view); break; case DS_VFS_PIPE: if (view->ds_vfs_pipe != -1) { (void) mc_close (view->ds_vfs_pipe); view->ds_vfs_pipe = -1; } mcview_growbuf_free (view); break; case DS_FILE: (void) mc_close (view->ds_file_fd); view->ds_file_fd = -1; MC_PTR_FREE (view->ds_file_data); break; case DS_STRING: MC_PTR_FREE (view->ds_string_data); break; default: #ifdef HAVE_ASSERT_H assert (!"Unknown datasource type") #endif ; } view->datasource = DS_NONE; }
void mcview_growbuf_read_until (mcview_t * view, off_t ofs) { ssize_t nread; byte *p; size_t bytesfree; gboolean short_read; assert (view->growbuf_in_use); if (view->growbuf_finished) return; short_read = FALSE; while (mcview_growbuf_filesize (view) < ofs || short_read) { if (view->growbuf_lastindex == VIEW_PAGE_SIZE) { /* Append a new block to the growing buffer */ byte *newblock = g_try_malloc (VIEW_PAGE_SIZE); if (newblock == NULL) return; g_ptr_array_add (view->growbuf_blockptr, newblock); view->growbuf_lastindex = 0; } p = g_ptr_array_index (view->growbuf_blockptr, view->growbuf_blockptr->len - 1) + view->growbuf_lastindex; bytesfree = VIEW_PAGE_SIZE - view->growbuf_lastindex; if (view->datasource == DS_STDIO_PIPE) { nread = fread (p, 1, bytesfree, view->ds_stdio_pipe); if (nread == 0) { view->growbuf_finished = TRUE; (void) pclose (view->ds_stdio_pipe); mcview_display (view); close_error_pipe (D_NORMAL, NULL); view->ds_stdio_pipe = NULL; return; } } else { assert (view->datasource == DS_VFS_PIPE); do { nread = mc_read (view->ds_vfs_pipe, p, bytesfree); } while (nread == -1 && errno == EINTR); if (nread == -1 || nread == 0) { view->growbuf_finished = TRUE; (void) mc_close (view->ds_vfs_pipe); view->ds_vfs_pipe = -1; return; } } short_read = ((size_t) nread < bytesfree); view->growbuf_lastindex += nread; } }
void mcview_growbuf_read_until (WView * view, off_t ofs) { gboolean short_read = FALSE; #ifdef HAVE_ASSERT_H assert (view->growbuf_in_use); #endif if (view->growbuf_finished) return; while (mcview_growbuf_filesize (view) < ofs || short_read) { ssize_t nread = 0; byte *p; size_t bytesfree; if (view->growbuf_lastindex == VIEW_PAGE_SIZE) { /* Append a new block to the growing buffer */ byte *newblock = g_try_malloc (VIEW_PAGE_SIZE); if (newblock == NULL) return; g_ptr_array_add (view->growbuf_blockptr, newblock); view->growbuf_lastindex = 0; } p = (byte *) g_ptr_array_index (view->growbuf_blockptr, view->growbuf_blockptr->len - 1) + view->growbuf_lastindex; bytesfree = VIEW_PAGE_SIZE - view->growbuf_lastindex; if (view->datasource == DS_STDIO_PIPE) { mc_pipe_t *sp = view->ds_stdio_pipe; GError *error = NULL; if (bytesfree > MC_PIPE_BUFSIZE) bytesfree = MC_PIPE_BUFSIZE; sp->out.len = bytesfree; sp->err.len = MC_PIPE_BUFSIZE; mc_pread (sp, &error); if (error != NULL) { mcview_show_error (view, error->message); g_error_free (error); mcview_growbuf_done (view); return; } if (view->pipe_first_err_msg && sp->err.len > 0) { /* ignore possible following errors */ /* reset this flag before call of mcview_show_error() to break * endless recursion: mcview_growbuf_read_until() -> mcview_show_error() -> * MSG_DRAW -> mcview_display() -> mcview_get_byte() -> mcview_growbuf_read_until() */ view->pipe_first_err_msg = FALSE; mcview_show_error (view, sp->err.buf); } if (sp->out.len > 0) { memmove (p, sp->out.buf, sp->out.len); nread = sp->out.len; } else if (sp->out.len == MC_PIPE_STREAM_EOF || sp->out.len == MC_PIPE_ERROR_READ) { if (sp->out.len == MC_PIPE_ERROR_READ) { char *err_msg; err_msg = g_strdup_printf (_("Failed to read data from child stdout:\n%s"), unix_error_string (sp->out.error)); mcview_show_error (view, err_msg); g_free (err_msg); } if (view->ds_stdio_pipe != NULL) { /* when switch from parse to raw mode and back, * do not close the already closed pipe after following loop: * mcview_growbuf_read_until() -> mcview_show_error() -> * MSG_DRAW -> mcview_display() -> mcview_get_byte() -> mcview_growbuf_read_until() */ mcview_growbuf_done (view); } mcview_display (view); return; } } else { #ifdef HAVE_ASSERT_H assert (view->datasource == DS_VFS_PIPE); #endif do { nread = mc_read (view->ds_vfs_pipe, p, bytesfree); } while (nread == -1 && errno == EINTR); if (nread <= 0) { mcview_growbuf_done (view); return; } } short_read = ((size_t) nread < bytesfree); view->growbuf_lastindex += nread; } }