static gpg_error_t create_pipe_and_estream (int filedes[2], estream_t *r_fp, int outbound, int nonblock) { gpg_error_t err; if (pipe (filedes) == -1) { err = my_error_from_syserror (); log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); filedes[0] = filedes[1] = -1; *r_fp = NULL; return err; } if (!outbound) *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r"); else *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w"); if (!*r_fp) { err = my_error_from_syserror (); log_error (_("error creating a stream for a pipe: %s\n"), gpg_strerror (err)); close (filedes[0]); close (filedes[1]); filedes[0] = filedes[1] = -1; return err; } return 0; }
static void create_pipe (estream_t *r_in, estream_t *r_out) { gpg_error_t err; int filedes[2]; #ifdef _WIN32 if (_pipe (filedes, 512, 0) == -1) #else if (pipe (filedes) == -1) #endif { err = gpg_error_from_syserror (); die ("error creating a pipe: %s\n", gpg_strerror (err)); } show ("created pipe [%d, %d]\n", filedes[0], filedes[1]); *r_in = es_fdopen (filedes[0], "r"); if (!*r_in) { err = gpg_error_from_syserror (); die ("error creating a stream for a pipe: %s\n", gpg_strerror (err)); } *r_out = es_fdopen (filedes[1], "w"); if (!*r_out) { err = gpg_error_from_syserror (); die ("error creating a stream for a pipe: %s\n", gpg_strerror (err)); } }
static gpg_error_t create_pipe_and_estream (int filedes[2], estream_t *r_fp, gpg_err_source_t errsource) { gpg_error_t err; if (pipe (filedes) == -1) { err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); filedes[0] = filedes[1] = -1; *r_fp = NULL; return err; } *r_fp = es_fdopen (filedes[0], "r"); if (!*r_fp) { err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); log_error (_("error creating a stream for a pipe: %s\n"), gpg_strerror (err)); close (filedes[0]); close (filedes[1]); filedes[0] = filedes[1] = -1; return err; } return 0; }
void set_status_fd (int fd) { static int last_fd = -1; if (fd != -1 && last_fd == fd) return; if (statusfp && statusfp != es_stdout && statusfp != es_stderr ) es_fclose (statusfp); statusfp = NULL; if (fd == -1) return; if (fd == 1) statusfp = es_stdout; else if (fd == 2) statusfp = es_stderr; else statusfp = es_fdopen (fd, "w"); if (!statusfp) { log_fatal ("can't open fd %d for status output: %s\n", fd, strerror (errno)); } last_fd = fd; gcry_set_progress_handler (progress_cb, NULL); }
/* Set the status FD. */ void wks_set_status_fd (int fd) { static int last_fd = -1; if (fd != -1 && last_fd == fd) return; if (statusfp && statusfp != es_stdout && statusfp != es_stderr) es_fclose (statusfp); statusfp = NULL; if (fd == -1) return; if (fd == 1) statusfp = es_stdout; else if (fd == 2) statusfp = es_stderr; else statusfp = es_fdopen (fd, "w"); if (!statusfp) { log_fatal ("can't open fd %d for status output: %s\n", fd, gpg_strerror (gpg_error_from_syserror ())); } last_fd = fd; }
/* Spawn a new thread to let RUNNER work as a coprocess. */ gpg_error_t runner_spawn (runner_t runner) { gpg_error_t err; npth_attr_t tattr; npth_t thread; int ret; if (check_already_spawned (runner, "runner_spawn")) return gpg_error (GPG_ERR_BUG); /* In case we have an input fd, open it as an estream so that the Pth scheduling will work. The stdio functions don't work with Pth because they don't call the pth counterparts of read and write unless linker tricks are used. */ if (runner->in_fd != -1) { estream_t fp; fp = es_fdopen (runner->in_fd, "r"); if (!fp) { err = gpg_error_from_syserror (); log_error ("can't fdopen pipe for reading: %s\n", gpg_strerror (err)); return err; } runner->status_fp = fp; runner->in_fd = -1; /* Now owned by status_fp. */ } npth_attr_init (&tattr); npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED); ret = npth_create (&thread, &tattr, runner_thread, runner); if (ret) { err = gpg_error_from_errno (ret); log_error ("error spawning runner thread: %s\n", gpg_strerror (err)); return err; } npth_setname_np (thread, runner->name); /* The scheduler has not yet kicked in, thus we can safely set the spawned flag and the tid. */ runner->spawned = 1; runner->thread = thread; runner->next_running = running_threads; running_threads = runner; npth_attr_destroy (&tattr); /* The runner thread is now runnable. */ return 0; }