Exemple #1
0
void
modes_pre(void)
{
	if(vle_mode_is(CMDLINE_MODE))
	{
		touchwin(status_bar);
		wrefresh(status_bar);
		return;
	}
	else if(ANY(vle_mode_is, SORT_MODE, CHANGE_MODE, ATTR_MODE))
	{
		return;
	}
	else if(vle_mode_is(VIEW_MODE))
	{
		view_pre();
		return;
	}
	else if(is_in_menu_like_mode())
	{
		menu_pre();
		return;
	}

	if(!curr_stats.save_msg)
	{
		clean_status_bar();
		wrefresh(status_bar);
	}
}
Exemple #2
0
static void
parse_recieved_arguments(char *args[])
{
	char lwin_path[PATH_MAX] = "";
	char rwin_path[PATH_MAX] = "";
	int lwin_handle = 0, rwin_handle = 0;
	int argc = 0;

	while(args[argc] != NULL)
	{
		argc++;
	}

	parse_args(argc, args, args[0], lwin_path, rwin_path, &lwin_handle,
			&rwin_handle);
	exec_startup_commands(argc, args);

	if(get_mode() != NORMAL_MODE && get_mode() != VIEW_MODE)
	{
		return;
	}

#ifdef _WIN32
	SwitchToThisWindow(GetConsoleWindow(), TRUE);
	BringWindowToTop(GetConsoleWindow());
	SetForegroundWindow(GetConsoleWindow());
#endif

	if(view_needs_cd(&lwin, lwin_path))
	{
		remote_cd(&lwin, lwin_path, lwin_handle);
	}

	if(view_needs_cd(&rwin, rwin_path))
	{
		remote_cd(&rwin, rwin_path, rwin_handle);
	}

	if(lwin_path[0] != '\0' && rwin_path[0] == '\0' && curr_view != &lwin)
	{
		change_window();
	}

	clean_status_bar();
	curr_stats.save_msg = 0;
}
Exemple #3
0
void
modes_statusbar_update(void)
{
	if(curr_stats.save_msg)
	{
		if(vle_mode_is(VISUAL_MODE))
		{
			update_vmode_input();
		}
	}
	else if(curr_view->selected_files || vle_mode_is(VISUAL_MODE))
	{
		print_selected_msg();
	}
	else
	{
		clean_status_bar();
	}
}
Exemple #4
0
static void
leave_cmdline_mode(void)
{
	int attr;

	if(getmaxy(status_bar) > 1)
	{
		curr_stats.need_redraw = 2;
		wresize(status_bar, 1, getmaxx(stdscr) - 19);
		mvwin(status_bar, getmaxy(stdscr) - 1, 0);
		if(prev_mode == MENU_MODE)
		{
			wresize(menu_win, getmaxy(stdscr) - 1, getmaxx(stdscr));
			update_menu();
		}
	}
	else
	{
		wresize(status_bar, 1, getmaxx(stdscr) - 19);
	}

	curs_set(FALSE);
	curr_stats.save_msg = 0;
	free(input_stat.line);
	free(input_stat.line_buf);
	clean_status_bar();

	if(*mode == CMDLINE_MODE)
		*mode = prev_mode;

	if(*mode != MENU_MODE)
		update_pos_window(curr_view);

	attr = cfg.cs.color[CMD_LINE_COLOR].attr;
	wattroff(status_bar, COLOR_PAIR(DCOLOR_BASE + CMD_LINE_COLOR) | attr);

	if(prev_mode != MENU_MODE && prev_mode != VIEW_MODE)
	{
		draw_dir_list(curr_view, curr_view->top_line);
		move_to_list_pos(curr_view, curr_view->list_pos);
	}
}
Exemple #5
0
static void
leave_cmdline_mode(void)
{
	int attr;

	if(getmaxy(status_bar) > 1)
	{
		curr_stats.need_update = UT_FULL;
		wresize(status_bar, 1, getmaxx(stdscr) - FIELDS_WIDTH);
		mvwin(status_bar, getmaxy(stdscr) - 1, 0);
		if(prev_mode == MENU_MODE)
		{
			wresize(menu_win, getmaxy(stdscr) - 1, getmaxx(stdscr));
			update_menu();
		}
	}
	else
	{
		wresize(status_bar, 1, getmaxx(stdscr) - FIELDS_WIDTH);
	}

	curs_set(FALSE);
	curr_stats.save_msg = 0;
	free(input_stat.line);
	free(input_stat.initial_line);
	free(input_stat.line_buf);
	clean_status_bar();

	if(*mode == CMDLINE_MODE)
		*mode = prev_mode;

	if(*mode != MENU_MODE)
		update_pos_window(curr_view);

	attr = cfg.cs.color[CMD_LINE_COLOR].attr;
	wattroff(status_bar, COLOR_PAIR(DCOLOR_BASE + CMD_LINE_COLOR) | attr);

	if(prev_mode != MENU_MODE && prev_mode != VIEW_MODE)
	{
		redraw_current_view();
	}
}
Exemple #6
0
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;
}
Exemple #7
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;
}
Exemple #8
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() */

	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;
}
void
event_loop(const int *quit)
{
	/* TODO: refactor this function event_loop(). */

	LOG_FUNC_ENTER;

	const wchar_t *const prev_input_buf = curr_input_buf;
	const size_t *const prev_input_buf_pos = curr_input_buf_pos;

	wchar_t input_buf[128];
	size_t input_buf_pos;

	int last_result = 0;
	int wait_for_enter = 0;
	int timeout = cfg.timeout_len;

	input_buf[0] = L'\0';
	input_buf_pos = 0;
	curr_input_buf = &input_buf[0];
	curr_input_buf_pos = &input_buf_pos;

	while(!*quit)
	{
		wint_t c;
		size_t counter;
		int got_input;

		if(!ensure_term_is_ready())
		{
			wait_for_enter = 0;
			continue;
		}

		lwin.user_selection = 1;
		rwin.user_selection = 1;

		modes_pre();

		/* Waits for timeout then skips if no keypress.  Short-circuit if we're not
		 * waiting for the next key after timeout. */
		do
		{
			modes_periodic();

			check_background_jobs();

			got_input = get_char_async_loop(status_bar, &c, timeout) != ERR;
			if(!got_input && input_buf_pos == 0)
			{
				timeout = cfg.timeout_len;
				continue;
			}
			break;
		}
		while(1);

		/* Ensure that current working directory is set correctly (some pieces of
		 * code rely on this). */
		(void)vifm_chdir(flist_get_dir(curr_view));

		if(got_input)
		{
			if(wait_for_enter)
			{
				wait_for_enter = 0;
				curr_stats.save_msg = 0;
				clean_status_bar();
				if(c == L'\x0d')
				{
					continue;
				}
			}

			if(c == L'\x1a') /* Ctrl-Z */
			{
				def_prog_mode();
				endwin();
				stop_process();
				continue;
			}

			if(input_buf_pos < ARRAY_LEN(input_buf) - 2)
			{
				input_buf[input_buf_pos++] = c;
				input_buf[input_buf_pos] = L'\0';
			}
			else
			{
				/* Recover from input buffer overflow by resetting its contents. */
				reset_input_buf(input_buf, &input_buf_pos);
				clear_input_bar();
				continue;
			}
		}

		counter = get_key_counter();
		if(!got_input && last_result == KEYS_WAIT_SHORT)
		{
			last_result = execute_keys_timed_out(input_buf);
			counter = get_key_counter() - counter;
			assert(counter <= input_buf_pos);
			if(counter > 0)
			{
				memmove(input_buf, input_buf + counter,
						(wcslen(input_buf) - counter + 1)*sizeof(wchar_t));
			}
		}
		else
		{
			if(got_input)
			{
				curr_stats.save_msg = 0;
			}

			last_result = execute_keys(input_buf);

			counter = get_key_counter() - counter;
			assert(counter <= input_buf_pos);
			if(counter > 0)
			{
				input_buf_pos -= counter;
				memmove(input_buf, input_buf + counter,
						(wcslen(input_buf) - counter + 1)*sizeof(wchar_t));
			}

			if(last_result == KEYS_WAIT || last_result == KEYS_WAIT_SHORT)
			{
				if(got_input)
				{
					modupd_input_bar(input_buf);
				}

				if(last_result == KEYS_WAIT_SHORT && wcscmp(input_buf, L"\033") == 0)
				{
					timeout = 1;
				}

				if(counter > 0)
				{
					clear_input_bar();
				}

				if(!curr_stats.save_msg && curr_view->selected_files &&
						!vle_mode_is(CMDLINE_MODE))
				{
					print_selected_msg();
				}
				continue;
			}
		}

		timeout = cfg.timeout_len;

		process_scheduled_updates();

		reset_input_buf(input_buf, &input_buf_pos);
		clear_input_bar();

		if(is_status_bar_multiline())
		{
			wait_for_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(flist_get_dir(curr_view));
		modes_post();
	}

	curr_input_buf = prev_input_buf;
	curr_input_buf_pos = prev_input_buf_pos;
}
Exemple #10
0
/*
 * 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();
	}
}