Exemple #1
0
int
capture_output_to_menu(FileView *view, const char cmd[], menu_info *m)
{
	FILE *file, *err;
	char *line = NULL;
	int x;
	pid_t pid;

	LOG_INFO_MSG("Capturing output of the command to a menu: %s", cmd);

	pid = background_and_capture((char *)cmd, &file, &err);
	if(pid == (pid_t)-1)
	{
		show_error_msgf("Trouble running command", "Unable to run: %s", cmd);
		return 0;
	}

	show_progress("", 0);

	ui_cancellation_reset();
	ui_cancellation_enable();

	wait_for_data_from(pid, file, 0);

	x = 0;
	while((line = read_line(file, line)) != NULL)
	{
		char *expanded_line;
		show_progress("Loading menu", 1000);
		m->items = realloc(m->items, sizeof(char *)*(x + 1));
		expanded_line = expand_tabulation_a(line, cfg.tab_stop);
		if(expanded_line != NULL)
		{
			m->items[x++] = expanded_line;
		}

		wait_for_data_from(pid, file, 0);
	}
	m->len = x;

	ui_cancellation_disable();

	fclose(file);
	print_errors(err);

	if(ui_cancellation_requested())
	{
		append_to_string(&m->title, "(cancelled) ");
		append_to_string(&m->empty_msg, " (cancelled)");
	}

	return display_menu(m, view);
}
Exemple #2
0
int
background_and_wait_for_errors(char cmd[], int cancellable)
{
#ifndef _WIN32
	pid_t pid;
	int error_pipe[2];
	int result = 0;

	if(pipe(error_pipe) != 0)
	{
		error_msg("File pipe error", "Error creating pipe");
		return -1;
	}

	(void)set_sigchld(1);

	if((pid = fork()) == -1)
	{
		(void)set_sigchld(0);
		return -1;
	}

	if(pid == 0)
	{
		(void)set_sigchld(0);
		run_from_fork(error_pipe, 1, cmd);
	}
	else
	{
		char buf[80*10];
		char linebuf[80];
		int nread = 0;

		close(error_pipe[1]); /* Close write end of pipe. */

		if(cancellable)
		{
			ui_cancellation_enable();
		}

		wait_for_data_from(pid, NULL, error_pipe[0]);

		buf[0] = '\0';
		while((nread = read(error_pipe[0], linebuf, sizeof(linebuf) - 1)) > 0)
		{
			const int read_empty_line = nread == 1 && linebuf[0] == '\n';
			result = -1;
			linebuf[nread] = '\0';

			if(!read_empty_line)
			{
				strncat(buf, linebuf, sizeof(buf) - strlen(buf) - 1);
			}

			wait_for_data_from(pid, NULL, error_pipe[0]);
		}
		close(error_pipe[0]);

		if(cancellable)
		{
			ui_cancellation_disable();
		}

		if(result != 0)
		{
			error_msg("Background Process Error", buf);
		}
		else
		{
			/* Don't use "const int" variables with WEXITSTATUS() as they cause
			 * compilation errors in case __USE_BSD is defined.  Anonymous type with
			 * "const int" is composed via compound literal expression. */
			int status = get_proc_exit_status(pid);
			result = (status != -1 && WIFEXITED(status)) ? WEXITSTATUS(status) : -1;
		}
	}

	(void)set_sigchld(0);

	return result;
#else
	return -1;
#endif
}