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); }
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 }