/* Navigates the view to given mark if it's valid. Returns new value for * save_msg flag. */ static int navigate_to_bookmark(FileView *view, char mark) { const bookmark_t *const bmark = get_bookmark(mark); if(is_bmark_valid(bmark)) { if(change_directory(view, bmark->directory) >= 0) { load_dir_list(view, 1); (void)ensure_file_is_selected(view, bmark->file); } } else { if(!char_is_one_of(valid_bookmarks, mark)) status_bar_message("Invalid mark name"); else if(is_bmark_empty(bmark)) status_bar_message("Mark is not set"); else status_bar_message("Mark is invalid"); move_to_list_pos(view, view->list_pos); return 1; } return 0; }
/* Navigates the view to given mark if it's valid. Returns new value for * save_msg flag. */ static int navigate_to_mark(FileView *view, char m) { const mark_t *const mark = get_mark_by_name(m); if(is_mark_valid(mark)) { navigate_to_file(view, mark->directory, mark->file); return 0; } if(!char_is_one_of(valid_marks, m)) { status_bar_message("Invalid mark name"); } else if(is_empty(mark)) { status_bar_message("Mark is not set"); } else { status_bar_message("Mark is invalid"); } fview_cursor_redraw(view); return 1; }
static void goto_bookmark (GtkWidget * menu_item, gchar *value) { GList *tmp; gint i; gchar *file; for(tmp = cfg.bookmarks; tmp != NULL; tmp = tmp->next) { Bookmarks *bk = tmp->data; if(!strcmp(value, bk->mark)) { change_dir(curr_view, bk->dir); gtk_clist_freeze(GTK_CLIST(curr_view->clist)); for(i = 0; i < GTK_CLIST(curr_view->clist)->rows; i++) { gtk_clist_get_text(GTK_CLIST(curr_view->clist), i, 0, &file); if(!strcmp(bk->file, file)) { focus_on_row(curr_view, i); gtk_clist_thaw(GTK_CLIST(curr_view->clist)); return; } } focus_on_row(curr_view, 0); gtk_clist_thaw(GTK_CLIST(curr_view->clist)); return; } } status_bar_message("Mark not found"); return; }
/* Ensures that terminal is in proper state for a loop iteration. Returns * non-zero if so, otherwise zero is returned. */ static int ensure_term_is_ready(void) { ui_update_term_state(); update_terminal_settings(); if(curr_stats.term_state == TS_TOO_SMALL) { ui_display_too_small_term_msg(); wait_for_signal(); return 0; } if(curr_stats.term_state == TS_BACK_TO_NORMAL) { wint_t c; wtimeout(status_bar, 0); while(compat_wget_wch(status_bar, &c) != ERR); curr_stats.term_state = TS_NORMAL; modes_redraw(); wtimeout(status_bar, cfg.timeout_len); curr_stats.save_msg = 0; status_bar_message(""); } return 1; }
void view_pre(void) { if(curr_stats.save_msg == 0) { status_bar_message("-- VIEW -- "); curr_stats.save_msg = 2; } }
void menu_post(void) { if(curr_stats.need_update != UT_NONE) { menu_redraw(); curr_stats.need_update = UT_NONE; } status_bar_message(curr_stats.save_msg ? NULL : ""); }
int set_user_bookmark(const char mark, const char directory[], const char file[]) { if(!is_user_bookmark(mark)) { status_bar_message("Invalid mark name"); return 1; } set_mark(mark, directory, file, time(NULL), 0); return 0; }
int find_pattern(FileView *view, char *pattern) { int found = 0; regex_t re; int x; int first_match = 0; int first_match_pos = 0; view->selected_files = 0; for(x = 0; x < view->list_rows; x++) { if(regcomp(&re, pattern, REG_EXTENDED) == 0) { if(regexec(&re, view->dir_entry[x].name, 0, NULL, 0) == 0) { if(!first_match) { first_match++; first_match_pos = x; } view->dir_entry[x].selected = 1; view->selected_files++; found++; } else view->dir_entry[x].selected = 0; } regfree(&re); } /* Need to redraw the list so that the matching files are highlighted */ draw_dir_list(view, view->top_line, view->curr_line); if(found) { draw_dir_list(view, view->top_line, view->curr_line); moveto_list_pos(view, first_match_pos); return 0; } else { char buf[48]; moveto_list_pos(view, view->list_pos); snprintf(buf, sizeof(buf), "No matching files for %s", view->regexp); status_bar_message(buf); return 1; } }
void toggle_tag_cb () { FileInfo *info = gtk_clist_get_row_data (GTK_CLIST (curr_view->clist), curr_view->row); gint row = curr_view->row; if (g_list_find (curr_view->tagged, info) != NULL) { curr_view->tagged = g_list_remove (curr_view->tagged, info); gtk_clist_set_background (GTK_CLIST (curr_view->clist), row, &CLIST_COLOR); status_bar_message("File removed from tag list"); } else { curr_view->tagged = g_list_append (curr_view->tagged, info); gtk_clist_unselect_all(GTK_CLIST(curr_view->clist)); gtk_clist_set_background (GTK_CLIST (curr_view->clist), row, &TAG_COLOR); status_bar_message("File is tagged"); } }
int unstash_menu(FileView *view) { static menu_data_t menu_data_storage; if(!menu_data_stash.initialized) { status_bar_message("No saved menu to display"); return 1; } reset_menu_data(&menu_data_storage); menu_data_storage = menu_data_stash; menu_data_stash.initialized = 0; menu_state.d = &menu_data_storage; return display_menu(menu_data_storage.state, view); }
int display_menu(menu_state_t *m, FileView *view) { if(m->d->len < 1) { status_bar_message(m->d->empty_msg); reset_menu_data(m->d); return 1; } init_menu_state(m, view); setup_menu(); draw_menu(m); move_to_menu_pos(m->d->pos, m); enter_menu_mode(m->d, view); return 0; }
int display_menu(menu_info *m, FileView *view) { if(m->len < 1) { status_bar_message(m->empty_msg); reset_popup_menu(m); return 1; } else { setup_menu(); draw_menu(m); move_to_menu_pos(m->pos, m); enter_menu_mode(m, view); return 0; } }
/* Navigates the view to a given dir/file combination specified by the path. */ static void navigate_to_selected_file(FileView *view, const char path[]) { /* Check whether target path is directory while we don't change current * working directory by invoking change_directory() function below. */ const int dst_is_dir = is_dir(path); char name[NAME_MAX]; char *dir = strdup(path); char *const last_slash = find_slashr(dir); if(last_slash == NULL) { copy_str(name, sizeof(name), dir); } else { *last_slash = '\0'; copy_str(name, sizeof(name), last_slash + 1); } if(change_directory(view, dir) >= 0) { status_bar_message("Finding the correct directory..."); wrefresh(status_bar); load_dir_list(view, 0); if(dst_is_dir) { strcat(name, "/"); } (void)ensure_file_is_selected(view, name); } else { show_error_msgf("Invalid path", "Cannot change dir to \"%s\"", dir); } free(dir); }
void print_search_fail_msg(const FileView *view, int backward) { const char *const regexp = cfg_get_last_search_pattern(); int cflags; regex_t re; int err; if(regexp[0] == '\0') { status_bar_message(""); return; } cflags = get_regexp_cflags(regexp); err = regcomp(&re, regexp, cflags); if(err != 0) { status_bar_errorf("Regexp (%s) error: %s", regexp, get_regexp_error(err, &re)); regfree(&re); return; } regfree(&re); if(cfg.wrap_scan) { status_bar_errorf("No matching files for: %s", regexp); } else if(backward) { status_bar_errorf("Search hit TOP without match for: %s", regexp); } else { status_bar_errorf("Search hit BOTTOM without match for: %s", regexp); } }
/* Executes the cmd and displays its output on the status bar. */ static void output_to_statusbar(const char cmd[]) { FILE *file, *err; char buf[2048]; char *lines; size_t len; int error; setup_shellout_env(); error = (background_and_capture((char *)cmd, 1, &file, &err) == (pid_t)-1); cleanup_shellout_env(); if(error) { show_error_msgf("Trouble running command", "Unable to run: %s", cmd); return; } lines = NULL; len = 0; while(fgets(buf, sizeof(buf), file) == buf) { char *p; chomp(buf); p = realloc(lines, len + 1 + strlen(buf) + 1); if(p != NULL) { lines = p; len += sprintf(lines + len, "%s%s", (len == 0) ? "": "\n", buf); } } fclose(file); fclose(err); status_bar_message((lines == NULL) ? "" : lines); free(lines); }
void modes_post(void) { if(ANY(vle_mode_is, CMDLINE_MODE, SORT_MODE, CHANGE_MODE, ATTR_MODE)) { return; } else if(vle_mode_is(VIEW_MODE)) { view_post(); return; } else if(is_in_menu_like_mode()) { menu_post(); return; } update_screen(curr_stats.need_update); if(curr_stats.save_msg) { status_bar_message(NULL); } if(!vle_mode_is(FILE_INFO_MODE) && curr_view->list_rows > 0) { if(!is_status_bar_multiline()) { update_stat_window(curr_view); ui_ruler_update(curr_view); } } modes_statusbar_update(); }
void modes_redraw(void) { LOG_FUNC_ENTER; static int in_here; if(curr_stats.load_stage < 2) { return; } if(in_here++ > 0) { /* TODO: is this still needed? Update scheduling might have solved issues * caused by asynchronous execution of this function in the past. */ return; } if(curr_stats.term_state != TS_NORMAL) { update_screen(UT_REDRAW); goto finish; } if(vle_mode_is(CMDLINE_MODE)) { redraw_cmdline(); goto finish; } else if(vle_primary_mode_is(MENU_MODE)) { menu_redraw(); if(vle_mode_is(MSG_MODE)) { redraw_msg_dialog(0); } goto finish; } else if(vle_mode_is(FILE_INFO_MODE)) { redraw_file_info_dialog(); goto finish; } update_screen(UT_REDRAW); if(curr_stats.save_msg) { status_bar_message(NULL); } if(vle_mode_is(SORT_MODE)) { redraw_sort_dialog(); } else if(vle_mode_is(CHANGE_MODE)) { redraw_change_dialog(); } else if(vle_mode_is(ATTR_MODE)) { redraw_attr_dialog(); } else if(vle_mode_is(VIEW_MODE)) { view_redraw(); } else if(vle_mode_is(MSG_MODE)) { redraw_msg_dialog(0); } finish: if(--in_here > 0) { modes_redraw(); } }
int fuse_try_unmount(FileView *view) { char buf[14 + PATH_MAX + 1]; fuse_mount_t *runner, *trailer; int status; fuse_mount_t *sniffer; char *escaped_mount_point; runner = fuse_mounts; trailer = NULL; while(runner) { if(paths_are_equal(runner->mount_point, view->curr_dir)) { break; } trailer = runner; runner = runner->next; } if(runner == NULL) { return 0; } /* we are exiting a top level dir */ escaped_mount_point = escape_filename(runner->mount_point, 0); snprintf(buf, sizeof(buf), "%s %s 2> /dev/null", curr_stats.fuse_umount_cmd, escaped_mount_point); LOG_INFO_MSG("FUSE unmount command: `%s`", buf); free(escaped_mount_point); /* Have to chdir to parent temporarily, so that this DIR can be unmounted. */ if(vifm_chdir(cfg.fuse_home) != 0) { show_error_msg("FUSE UMOUNT ERROR", "Can't chdir to FUSE home"); return -1; } status_bar_message("FUSE unmounting selected file, please stand by.."); status = background_and_wait_for_status(buf, 0, NULL); clean_status_bar(); /* check child status */ if(!WIFEXITED(status) || WEXITSTATUS(status)) { werase(status_bar); show_error_msgf("FUSE UMOUNT ERROR", "Can't unmount %s. It may be busy.", runner->source_file_name); (void)vifm_chdir(flist_get_dir(view)); return -1; } /* remove the directory we created for the mount */ if(path_exists(runner->mount_point, DEREF)) rmdir(runner->mount_point); /* remove mount point from fuse_mount_t */ sniffer = runner->next; if(trailer) trailer->next = sniffer ? sniffer : NULL; else fuse_mounts = sniffer; updir_from_mount(view, runner); free(runner); return 1; }
void redraw_window(void) { int screen_x, screen_y; int x, y; struct winsize ws; curr_stats.freeze = 1; ioctl(0, TIOCGWINSZ, &ws); // changed for pdcurses resize_term(ws.ws_row, ws.ws_col); getmaxyx(stdscr, screen_y, screen_x); if (screen_y < 10) finish("Terminal is too small to run vifm\n"); if (screen_x < 30) finish("Terminal is too small to run vifm\n"); wclear(stdscr); wclear(lwin.title); wclear(lwin.win); wclear(rwin.title); wclear(rwin.win); wclear(stat_win); wclear(status_bar); wclear(pos_win); wclear(num_win); wclear(rborder); wclear(mborder); wclear(lborder); wclear(change_win); wclear(sort_win); wresize(stdscr, screen_y, screen_x); mvwin(sort_win, (screen_y - 14)/2, (screen_x -30)/2); mvwin(change_win, (screen_y - 10)/2, (screen_x -30)/2); wresize(menu_win, screen_y - 1, screen_x); wresize(error_win, (screen_y -10)/2, screen_x -2); mvwin(error_win, (screen_y -10)/2, 1); wresize(lborder, screen_y -2, 1); if (curr_stats.number_of_windows == 1) { wresize(lwin.title, 1, screen_x -1); wresize(lwin.win, screen_y -3, screen_x -2); getmaxyx(lwin.win, y, x); lwin.window_width = x -1; lwin.window_rows = y -1; wresize(rwin.title, 1, screen_x -1); mvwin(rwin.title, 0, 1); wresize(rwin.win, screen_y -3, screen_x -2); mvwin(rwin.win, 1, 1); getmaxyx(rwin.win, y, x); rwin.window_width = x -1; rwin.window_rows = y -1; } else { wresize(lwin.title, 1, screen_x/2 -2); wresize(lwin.win, screen_y -3, screen_x/2 -2); getmaxyx(lwin.win, y, x); lwin.window_width = x -1; lwin.window_rows = y -1; mvwin(mborder, 0, screen_x/2 -1); wresize(mborder, screen_y, 2); wresize(rwin.title, 1, screen_x/2 -2); mvwin(rwin.title, 0, screen_x/2 +1); wresize(rwin.win, screen_y -3, screen_x/2 -2); mvwin(rwin.win, 1, screen_x/2 +1); getmaxyx(rwin.win, y, x); rwin.window_width = x -1; rwin.window_rows = y -1; } /* For FreeBSD */ keypad(lwin.win, TRUE); keypad(rwin.win, TRUE); if (screen_x % 2) { wresize(rborder, screen_y -2, 2); mvwin(rborder, 0, screen_x -2); } else { wresize(rborder, screen_y -2, 1); mvwin(rborder, 0, screen_x -1); } wresize(stat_win, 1, screen_x); mvwin(stat_win, screen_y -2, 0); wresize(status_bar, 1, screen_x -19); /* For FreeBSD */ keypad(status_bar, TRUE); mvwin(status_bar, screen_y -1, 0); wresize(pos_win, 1, 13); mvwin(pos_win, screen_y -1, screen_x -13); wresize(num_win, 1, 6); mvwin(num_win, screen_y -1, screen_x -19); curs_set(0); change_directory(&rwin, rwin.curr_dir); load_dir_list(&rwin, 0); change_directory(&lwin, lwin.curr_dir); load_dir_list(&lwin, 0); if(curr_stats.view) { wclear(other_view->win); change_directory(curr_view, curr_view->curr_dir); load_dir_list(curr_view, 0); quick_view_file(curr_view); } else change_directory(curr_view, curr_view->curr_dir); update_stat_window(curr_view); if (curr_view->selected_files) { char status_buf[24]; snprintf(status_buf, sizeof(status_buf), "%d %s Selected", curr_view->selected_files, curr_view->selected_files == 1 ? "File" : "Files"); status_bar_message(status_buf); } else status_bar_message(" "); update_pos_window(curr_view); update_all_windows(); moveto_list_pos(curr_view, curr_view->list_pos); wrefresh(curr_view->win); curr_stats.freeze = 0; curr_stats.need_redraw = 0; }
/* mount_point should be an array of at least PATH_MAX characters * Returns non-zero on error. */ static int fuse_mount(FileView *view, char file_full_path[], const char param[], const char program[], char mount_point[]) { /* TODO: refactor this function fuse_mount(). */ int mount_point_id; char buf[2*PATH_MAX]; char *escaped_filename; int foreground; char errors_file[PATH_MAX]; int status; int cancelled; escaped_filename = escape_filename(get_current_file_name(view), 0); mount_point_id = get_last_mount_point_id(fuse_mounts); do { snprintf(mount_point, PATH_MAX, "%s/%03d_%s", cfg.fuse_home, ++mount_point_id, get_current_file_name(view)); } while(path_exists(mount_point, DEREF)); if(os_mkdir(mount_point, S_IRWXU) != 0) { free(escaped_filename); show_error_msg("Unable to create FUSE mount directory", mount_point); return -1; } free(escaped_filename); /* Just before running the mount, I need to chdir out temporarily from any FUSE mounted paths, Otherwise the fuse-zip command fails with "fusermount: failed to open current directory: permission denied" (this happens when mounting JARs from mounted JARs) */ if(vifm_chdir(cfg.fuse_home) != 0) { show_error_msg("FUSE MOUNT ERROR", "Can't chdir() to FUSE home"); return -1; } format_mount_command(mount_point, file_full_path, param, program, sizeof(buf), buf, &foreground); status_bar_message("FUSE mounting selected file, please stand by.."); if(foreground) { def_prog_mode(); endwin(); } generate_tmp_file_name("vifm.errors", errors_file, sizeof(errors_file)); strcat(buf, " 2> "); strcat(buf, errors_file); LOG_INFO_MSG("FUSE mount command: `%s`", buf); status = background_and_wait_for_status(buf, !foreground, &cancelled); clean_status_bar(); /* Check child process exit status. */ if(!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) { FILE *ef; if(!WIFEXITED(status)) { LOG_ERROR_MSG("FUSE mounter didn't exit!"); } else { LOG_ERROR_MSG("FUSE mount command exit status: %d", WEXITSTATUS(status)); } ef = os_fopen(errors_file, "r"); if(ef == NULL) { LOG_SERROR_MSG(errno, "Failed to open temporary stderr file: %s", errors_file); } show_errors_from_file(ef, "FUSE mounter error"); werase(status_bar); if(cancelled) { status_bar_message("FUSE mount cancelled"); curr_stats.save_msg = 1; } else { show_error_msg("FUSE MOUNT ERROR", file_full_path); } if(unlink(errors_file) != 0) { LOG_SERROR_MSG(errno, "Error file deletion failure: %d", errors_file); } /* Remove the directory we created for the mount. */ (void)rmdir(mount_point); (void)vifm_chdir(flist_get_dir(view)); return -1; } unlink(errors_file); status_bar_message("FUSE mount success"); register_mount(&fuse_mounts, file_full_path, mount_point, mount_point_id); return 0; }
int compare_two_panes(CompareType ct, ListType lt, int group_paths, int skip_empty) { int next_id = 1; entries_t curr, other; trie_t *const trie = trie_create(); ui_cancellation_reset(); ui_cancellation_enable(); curr = make_diff_list(trie, curr_view, &next_id, ct, skip_empty, 0); other = make_diff_list(trie, other_view, &next_id, ct, skip_empty, lt == LT_DUPS); ui_cancellation_disable(); trie_free_with_data(trie, &free_compare_records); /* Clear progress message displayed by make_diff_list(). */ ui_sb_quick_msg_clear(); if(ui_cancellation_requested()) { free_dir_entries(curr_view, &curr.entries, &curr.nentries); free_dir_entries(other_view, &other.entries, &other.nentries); status_bar_message("Comparison has been cancelled"); return 1; } if(!group_paths || lt != LT_ALL) { /* Sort both lists according to unique file numbers to group identical files * (sorting is stable, tags are set in make_diff_list()). */ qsort(curr.entries, curr.nentries, sizeof(*curr.entries), &id_sorter); qsort(other.entries, other.nentries, sizeof(*other.entries), &id_sorter); } if(lt == LT_UNIQUE) { make_unique_lists(curr, other); return 0; } if(lt == LT_DUPS) { leave_only_dups(&curr, &other); } flist_custom_start(curr_view, lt == LT_ALL ? "diff" : "dups diff"); flist_custom_start(other_view, lt == LT_ALL ? "diff" : "dups diff"); fill_side_by_side(curr, other, group_paths); if(flist_custom_finish(curr_view, CV_DIFF, 0) != 0) { show_error_msg("Comparison", "No results to display"); return 0; } if(flist_custom_finish(other_view, CV_DIFF, 0) != 0) { assert(0 && "The error shouldn't be happening here."); } curr_view->list_pos = 0; other_view->list_pos = 0; curr_view->custom.diff_cmp_type = ct; other_view->custom.diff_cmp_type = ct; curr_view->custom.diff_path_group = group_paths; other_view->custom.diff_path_group = group_paths; assert(curr_view->list_rows == other_view->list_rows && "Diff views must be in sync!"); ui_view_schedule_redraw(curr_view); ui_view_schedule_redraw(other_view); return 0; }
int compare_one_pane(FileView *view, CompareType ct, ListType lt, int skip_empty) { int i, dup_id; FileView *other = (view == curr_view) ? other_view : curr_view; const char *const title = (lt == LT_ALL) ? "compare" : (lt == LT_DUPS) ? "dups" : "nondups"; int next_id = 1; entries_t curr; trie_t *trie = trie_create(); ui_cancellation_reset(); ui_cancellation_enable(); curr = make_diff_list(trie, view, &next_id, ct, skip_empty, 0); ui_cancellation_disable(); trie_free_with_data(trie, &free_compare_records); /* Clear progress message displayed by make_diff_list(). */ ui_sb_quick_msg_clear(); if(ui_cancellation_requested()) { free_dir_entries(view, &curr.entries, &curr.nentries); status_bar_message("Comparison has been cancelled"); return 1; } qsort(curr.entries, curr.nentries, sizeof(*curr.entries), &id_sorter); flist_custom_start(view, title); dup_id = -1; next_id = 0; for(i = 0; i < curr.nentries; ++i) { dir_entry_t *entry = &curr.entries[i]; if(lt == LT_ALL) { flist_custom_put(view, entry); continue; } if(entry->id == dup_id) { put_or_free(view, entry, next_id, lt == LT_DUPS); continue; } dup_id = (i < curr.nentries - 1 && entry[0].id == entry[1].id) ? entry->id : -1; if(entry->id == dup_id) { put_or_free(view, entry, ++next_id, lt == LT_DUPS); continue; } put_or_free(view, entry, next_id, lt == LT_UNIQUE); } /* Entries' data has been moved out of them or freed, so need to free only the * list. */ dynarray_free(curr.entries); if(flist_custom_finish(view, lt == LT_UNIQUE ? CV_REGULAR : CV_COMPARE, 0) != 0) { show_error_msg("Comparison", "No results to display"); return 0; } /* Leave the other pane, if it's in the CV_DIFF mode, two panes are needed for * this. */ if(other->custom.type == CV_DIFF) { cd_updir(other, 1); } view->list_pos = 0; ui_view_schedule_redraw(view); return 0; }
void screen_status_message(const char *msg) { status_bar_message(&screen.status_bar, msg); }
/* * Main Loop * Everything is driven from this function with the exception of * signals which are handled in signals.c */ void main_loop(void) { LOG_FUNC_ENTER; int last_result = 0; int wait_enter = 0; int timeout = cfg.timeout_len; buf[0] = L'\0'; while(1) { wchar_t c; size_t counter; int ret; is_term_working(); #ifdef _WIN32 update_win_console(); #endif lwin.user_selection = 1; rwin.user_selection = 1; if(curr_stats.too_small_term > 0) { touchwin(stdscr); wrefresh(stdscr); mvwin(status_bar, 0, 0); wresize(status_bar, getmaxy(stdscr), getmaxx(stdscr)); werase(status_bar); waddstr(status_bar, "Terminal is too small for vifm"); touchwin(status_bar); wrefresh(status_bar); #ifndef _WIN32 pause(); #endif continue; } else if(curr_stats.too_small_term < 0) { wtimeout(status_bar, 0); while(wget_wch(status_bar, (wint_t*)&c) != ERR); curr_stats.too_small_term = 0; modes_redraw(); wtimeout(status_bar, cfg.timeout_len); wait_enter = 0; curr_stats.save_msg = 0; status_bar_message(""); } modes_pre(); /* This waits for timeout then skips if no keypress. */ ret = read_char(status_bar, (wint_t*)&c, timeout); /* Ensure that current working directory is set correctly (some pieces of * code rely on this). */ (void)vifm_chdir(curr_view->curr_dir); if(ret != ERR && pos != ARRAY_LEN(buf) - 2) { if(c == L'\x1a') /* Ctrl-Z */ { def_prog_mode(); endwin(); #ifndef _WIN32 { void (*saved_stp_sig_handler)(int) = signal(SIGTSTP, SIG_DFL); kill(0, SIGTSTP); signal(SIGTSTP, saved_stp_sig_handler); } #endif continue; } if(wait_enter) { wait_enter = 0; curr_stats.save_msg = 0; clean_status_bar(); if(c == L'\x0d') continue; } buf[pos++] = c; buf[pos] = L'\0'; } if(wait_enter && ret == ERR) continue; counter = get_key_counter(); if(ret == ERR && last_result == KEYS_WAIT_SHORT) { last_result = execute_keys_timed_out(buf); counter = get_key_counter() - counter; assert(counter <= pos); if(counter > 0) { memmove(buf, buf + counter, (wcslen(buf) - counter + 1)*sizeof(wchar_t)); } } else { if(ret != ERR) curr_stats.save_msg = 0; last_result = execute_keys(buf); counter = get_key_counter() - counter; assert(counter <= pos); if(counter > 0) { pos -= counter; memmove(buf, buf + counter, (wcslen(buf) - counter + 1)*sizeof(wchar_t)); } if(last_result == KEYS_WAIT || last_result == KEYS_WAIT_SHORT) { if(ret != ERR) modupd_input_bar(buf); if(last_result == KEYS_WAIT_SHORT && wcscmp(buf, L"\033") == 0) timeout = 1; if(counter > 0) clear_input_bar(); if(!curr_stats.save_msg && curr_view->selected_files && get_mode() != CMDLINE_MODE) print_selected_msg(); continue; } } timeout = cfg.timeout_len; process_scheduled_updates(); pos = 0; buf[0] = L'\0'; clear_input_bar(); if(is_status_bar_multiline()) { wait_enter = 1; update_all_windows(); continue; } /* Ensure that current working directory is set correctly (some pieces of * code rely on this). PWD could be changed during command execution, but * it should be correct for modes_post() in case of preview modes. */ (void)vifm_chdir(curr_view->curr_dir); modes_post(); } }
/* * mount_point should be an array of at least PATH_MAX characters * Returns non-zero on error. */ static int fuse_mount(FileView *view, char *file_full_path, const char *param, const char *program, char *mount_point) { /* TODO: refactor this function fuse_mount() */ fuse_mount_t *runner = NULL; int mount_point_id = 0; fuse_mount_t *fuse_item = NULL; char buf[2*PATH_MAX]; char *escaped_filename; int clear_before_mount = 0; char errors_file[PATH_MAX]; int status; escaped_filename = escape_filename(get_current_file_name(view), 0); /* get mount_point_id + mount_point and set runner pointing to the list's * tail */ if(fuse_mounts != NULL) { runner = fuse_mounts; while(runner->next != NULL) runner = runner->next; mount_point_id = runner->mount_point_id; } do { snprintf(mount_point, PATH_MAX, "%s/%03d_%s", cfg.fuse_home, ++mount_point_id, get_current_file_name(view)); } while(path_exists(mount_point)); if(make_dir(mount_point, S_IRWXU) != 0) { free(escaped_filename); show_error_msg("Unable to create FUSE mount directory", mount_point); return -1; } free(escaped_filename); /* Just before running the mount, I need to chdir out temporarily from any FUSE mounted paths, Otherwise the fuse-zip command fails with "fusermount: failed to open current directory: permission denied" (this happens when mounting JARs from mounted JARs) */ if(vifm_chdir(cfg.fuse_home) != 0) { show_error_msg("FUSE MOUNT ERROR", "Can't chdir() to FUSE home"); return -1; } clear_before_mount = format_mount_command(mount_point, file_full_path, param, program, sizeof(buf), buf); status_bar_message("FUSE mounting selected file, please stand by.."); if(clear_before_mount) { def_prog_mode(); endwin(); } generate_tmp_file_name("vifm.errors", errors_file, sizeof(errors_file)); strcat(buf, " 2> "); strcat(buf, errors_file); LOG_INFO_MSG("FUSE mount command: `%s`", buf); status = background_and_wait_for_status(buf); clean_status_bar(); /* check child status */ if(!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { FILE *ef = fopen(errors_file, "r"); print_errors(ef); unlink(errors_file); werase(status_bar); /* remove the directory we created for the mount */ if(path_exists(mount_point)) rmdir(mount_point); show_error_msg("FUSE MOUNT ERROR", file_full_path); (void)vifm_chdir(view->curr_dir); return -1; } unlink(errors_file); status_bar_message("FUSE mount success"); fuse_item = malloc(sizeof(*fuse_item)); copy_str(fuse_item->source_file_name, sizeof(fuse_item->source_file_name), file_full_path); strcpy(fuse_item->source_file_dir, view->curr_dir); canonicalize_path(mount_point, fuse_item->mount_point, sizeof(fuse_item->mount_point)); fuse_item->mount_point_id = mount_point_id; fuse_item->next = NULL; if(fuse_mounts == NULL) fuse_mounts = fuse_item; else runner->next = fuse_item; return 0; }