int run_in_shell_no_cls(char command[]) { typedef void (*sig_handler)(int); int pid; int result; extern char **environ; sig_handler sigtstp_handler; if(command == NULL) return 1; sigtstp_handler = signal(SIGTSTP, SIG_DFL); /* We need to block SIGCHLD signal. One can't just set it to SIG_DFL, because * it will possibly cause missing of SIGCHLD from a background process * (job). */ (void)set_sigchld(1); pid = fork(); if(pid == -1) { signal(SIGTSTP, sigtstp_handler); (void)set_sigchld(0); return -1; } if(pid == 0) { char *args[4]; signal(SIGTSTP, SIG_DFL); signal(SIGINT, SIG_DFL); (void)set_sigchld(0); args[0] = cfg.shell; args[1] = "-c"; args[2] = command; args[3] = NULL; execve(cfg.shell, args, environ); exit(127); } result = get_proc_exit_status(pid); signal(SIGTSTP, sigtstp_handler); (void)set_sigchld(0); return result; }
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 }