--- src/text.c.orig 2018-06-02 10:20:07.000000000 +0200 +++ src/text.c 2018-06-06 15:13:16.722468833 +0200 @@ -30,6 +30,8 @@ #include #include #include +#include +#include #ifndef NANO_TINY static pid_t pid = -1; @@ -1124,6 +1126,51 @@ fclose(tube); } +struct send_data_arg +{ + const filestruct *line; + int fd; +}; + +static void *send_data_thread(void *data) +{ + const filestruct *line = ((struct send_data_arg *)data)->line; + int fd = ((struct send_data_arg *)data)->fd; + free(data); + + send_data(line, fd); + free_filestruct(line); + close(fd); + + return NULL; +} + +static int create_send_data_thread(pthread_t* thr, const filestruct *line, int fd) +{ + struct send_data_arg *arg = (struct send_data_arg *) + malloc(sizeof(struct send_data_arg)); + + if (arg == NULL) { + return -1; + } + + arg->line = copy_filestruct(line); + arg->fd = fd; + + if (arg->line == NULL) { + free(arg); + return -1; + } + + if (pthread_create(thr, NULL, send_data_thread, arg) != 0) { + free_filestruct(arg->line); + free(arg); + return -1; + } + + return 0; +} + /* Execute the given command in a shell. Return TRUE on success. */ bool execute_command(const char *command) { @@ -1136,6 +1183,10 @@ /* Original and temporary handlers for SIGINT. */ bool setup_failed = FALSE; /* Whether setting up the temporary SIGINT handler failed. */ + posix_spawn_file_actions_t fa; + int fa_err = 0; + pthread_t thr; + char* shellargv[4]; /* Create a pipe to read the command's output from, and, if needed, * a pipe to feed the command's input through. */ @@ -1149,6 +1200,41 @@ if (shellenv == NULL) shellenv = (char *) "/bin/sh"; + if (posix_spawn_file_actions_init(&fa) != 0) { + statusbar(_("POSIX spawn failed")); + close(from_fd[0]); + close(from_fd[1]); + if (should_pipe) { + close(to_fd[0]); + close(to_fd[1]); + } + return FALSE; + } + + shellargv[0] = (char*)tail(shellenv); + shellargv[1] = "-c"; + shellargv[2] = (char*)(should_pipe ? &command[1] : command); + shellargv[3] = NULL; + + fa_err |= posix_spawn_file_actions_addclose(&fa, from_fd[0]); + fa_err |= posix_spawn_file_actions_adddup2(&fa, from_fd[1], fileno(stdout)); + fa_err |= posix_spawn_file_actions_adddup2(&fa, from_fd[1], fileno(stderr)); + fa_err |= posix_spawn_file_actions_addclose(&fa, from_fd[1]); + + if (should_pipe) { + fa_err |= posix_spawn_file_actions_adddup2(&fa, to_fd[0], fileno(stdin)); + fa_err |= posix_spawn_file_actions_addclose(&fa, to_fd[0]); + fa_err |= posix_spawn_file_actions_addclose(&fa, to_fd[1]); + } + + if (fa_err != 0 || + posix_spawn(&pid, shellenv, &fa, NULL, shellargv, NULL) != 0) { + pid = -1; + } + + posix_spawn_file_actions_destroy(&fa); + +#if 0 /* Fork a child process to run the command in. */ if ((pid = fork()) == 0) { /* Child: close the unused read end of the output pipe. */ @@ -1171,13 +1257,21 @@ /* If the exec call returns, there was an error. */ exit(1); } +#endif /* Parent: close the unused write end of the pipe. */ close(from_fd[1]); if (pid == -1) { - statusbar(_("Could not fork")); + statusbar(_("POSIX spawn failed")); +#if 0 + statusbar(_("Could not fork")); +#endif close(from_fd[0]); + if (should_pipe) { + close(to_fd[0]); + close(to_fd[1]); + } return FALSE; } @@ -1204,6 +1298,14 @@ update_undo(CUT); } + if (create_send_data_thread(&thr, + cutbuffer != NULL ? cutbuffer : openfile->fileage, to_fd[1]) != 0) { + close(to_fd[1]); + } + + close(to_fd[0]); + +#if 0 if (fork() == 0) { close(to_fd[0]); send_data(cutbuffer != NULL ? cutbuffer : openfile->fileage, to_fd[1]); @@ -1213,6 +1315,7 @@ close(to_fd[0]); close(to_fd[1]); +#endif #ifdef ENABLE_MULTIBUFFER if (ISSET(MULTIBUFFER)) @@ -1250,6 +1353,11 @@ if (wait(NULL) == -1) nperror("wait"); + if (should_pipe) { + void* ptr; + pthread_join(thr, &ptr); + } + /* If it was changed, restore the handler for SIGINT. */ if (!setup_failed && sigaction(SIGINT, &oldaction, NULL) == -1) nperror("sigaction"); @@ -3027,6 +3135,7 @@ pid_t pid_lint; static char **lintargs = NULL; lintstruct *lints = NULL, *tmplint = NULL, *curlint = NULL; + posix_spawn_file_actions_t fa; if (ISSET(RESTRICTED)) { show_restricted_warning(); @@ -3065,6 +3174,24 @@ construct_argument_list(&lintargs, openfile->syntax->linter, openfile->filename); + if (posix_spawn_file_actions_init(&fa) != 0) { + statusbar(_("POSIX spawn failed")); + close(lint_fd[0]); + close(lint_fd[1]); + return; + } + + if (posix_spawn_file_actions_addclose(&fa, lint_fd[0]) != 0 || + posix_spawn_file_actions_adddup2(&fa, lint_fd[1], STDOUT_FILENO) != 0 || + posix_spawn_file_actions_adddup2(&fa, lint_fd[1], STDERR_FILENO) != 0 || + posix_spawn_file_actions_addclose(&fa, lint_fd[1]) != 0 || + posix_spawnp(&pid_lint, lintargs[0], &fa, NULL, lintargs, NULL) != 0) { + pid_lint = -1; + } + + posix_spawn_file_actions_destroy(&fa); + +#if 0 /* Start a new process to run the linter in. */ if ((pid_lint = fork()) == 0) { @@ -3085,6 +3212,7 @@ /* This is only reached when the linter is not found. */ exit(9); } +#endif /* Parent continues here. */ close(lint_fd[1]); @@ -3092,7 +3220,10 @@ /* If the child process was not forked successfully... */ if (pid_lint < 0) { close(lint_fd[0]); - statusbar(_("Could not fork")); +#if 0 + statusbar(_("Could not fork")); +#endif + statusbar(_("POSIX spawn failed")); return; }