summaryrefslogtreecommitdiff
path: root/egg/egg-spawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'egg/egg-spawn.c')
-rw-r--r--egg/egg-spawn.c377
1 files changed, 0 insertions, 377 deletions
diff --git a/egg/egg-spawn.c b/egg/egg-spawn.c
deleted file mode 100644
index 46f409ba..00000000
--- a/egg/egg-spawn.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * gnome-keyring
- *
- * Copyright (C) 2009 Stefan Walter
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include "egg-spawn.h"
-
-#include <glib/gi18n-lib.h>
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/select.h>
-#include <sys/wait.h>
-
-typedef struct _CallbackSource {
- GSource source;
- EggSpawnCallbacks callbacks;
- GPollFD polls[3];
-} CallbackSource;
-
-static void
-close_fd (int *fd)
-{
- g_assert (fd);
- if (*fd >= 0)
- close (*fd);
- *fd = -1;
-}
-
-static void
-close_poll (GSource *source, GPollFD *poll)
-{
- g_source_remove_poll (source, poll);
- close_fd (&poll->fd);
- poll->revents = 0;
-}
-
-static gboolean
-unused_callback (gpointer data)
-{
- /* Never called */
- g_assert_not_reached ();
- return FALSE;
-}
-
-static gboolean
-cb_source_prepare (GSource *source, gint *timeout_)
-{
- CallbackSource *cb_source = (CallbackSource*)source;
- gint i;
-
- for (i = 0; i < 3; ++i) {
- if (cb_source->polls[i].fd >= 0)
- return FALSE;
- }
-
- /* If none of the FDs are valid, then process immediately */
- return TRUE;
-}
-
-static gboolean
-cb_source_check (GSource *source)
-{
- CallbackSource *cb_source = (CallbackSource*)source;
- gint i;
-
- for (i = 0; i < 3; ++i) {
- if (cb_source->polls[i].fd >= 0 && cb_source->polls[i].revents != 0)
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-cb_source_finalize (GSource *source)
-{
- CallbackSource *cb_source = (CallbackSource*)source;
- gint i;
-
- for (i = 0; i < 3; ++i)
- close_fd (&cb_source->polls[i].fd);
-}
-
-static gboolean
-cb_source_dispatch (GSource *source, GSourceFunc unused, gpointer user_data)
-{
- CallbackSource *cb_source = (CallbackSource*)source;
- GPollFD *poll;
- gint i;
-
- /* Standard input */
- poll = &cb_source->polls[0];
- if (poll->fd >= 0 && poll->revents != 0) {
- g_assert (cb_source->callbacks.standard_input);
- if (!(cb_source->callbacks.standard_input) (poll->fd, user_data))
- close_poll (source, poll);
- }
-
- /* Standard output */
- poll = &cb_source->polls[1];
- if (poll->fd >= 0 && poll->revents != 0) {
- g_assert (cb_source->callbacks.standard_output);
- if (!(cb_source->callbacks.standard_output) (poll->fd, user_data))
- close_poll (source, poll);
- }
-
- /* Standard error */
- poll = &cb_source->polls[2];
- if (poll->fd >= 0 && poll->revents != 0) {
- g_assert (cb_source->callbacks.standard_error);
- if (!(cb_source->callbacks.standard_error) (poll->fd, user_data))
- close_poll (source, poll);
- }
-
- for (i = 0; i < 3; ++i) {
- if (cb_source->polls[i].fd >= 0)
- return TRUE;
- }
-
- /* All input and output is done */
- if (cb_source->callbacks.completed)
- (cb_source->callbacks.completed) (user_data);
- return FALSE;
-}
-
-static GSourceFuncs cb_source_funcs = {
- cb_source_prepare,
- cb_source_check,
- cb_source_dispatch,
- cb_source_finalize,
-};
-
-guint
-egg_spawn_async_with_callbacks (const gchar *working_directory, gchar **argv,
- gchar **envp, GSpawnFlags flags, GPid *child_pid,
- EggSpawnCallbacks *cbs, gpointer user_data,
- GMainContext *context, GError **error)
-{
- gint in_fd, out_fd, err_fd;
- CallbackSource *cb_source;
- GSource *source;
- guint tag;
-
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail ((cbs && cbs->standard_input == NULL) ||
- !(flags & G_SPAWN_CHILD_INHERITS_STDIN), 0);
- g_return_val_if_fail ((cbs && cbs->standard_output == NULL) ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), 0);
- g_return_val_if_fail ((cbs && cbs->standard_error == NULL) ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), 0);
-
- in_fd = out_fd = err_fd = -1;
-
- if (!g_spawn_async_with_pipes (working_directory, argv, envp, flags,
- cbs ? cbs->child_setup : NULL,
- user_data, child_pid,
- cbs && cbs->standard_input ? &in_fd : NULL,
- cbs && cbs->standard_output ? &out_fd : NULL,
- cbs && cbs->standard_error ? &err_fd : NULL,
- error))
- return 0;
-
- source = g_source_new (&cb_source_funcs, sizeof (CallbackSource));
-
- cb_source = (CallbackSource*)source;
- if (cbs != NULL)
- memcpy (&cb_source->callbacks, cbs, sizeof (EggSpawnCallbacks));
-
- cb_source->polls[0].fd = in_fd;
- if (in_fd >= 0) {
- g_assert (cb_source->callbacks.standard_input);
- cb_source->polls[0].events = G_IO_ERR | G_IO_OUT;
- g_source_add_poll (source, &cb_source->polls[0]);
- }
- cb_source->polls[1].fd = out_fd;
- if (out_fd >= 0) {
- g_assert (cb_source->callbacks.standard_output);
- cb_source->polls[1].events = G_IO_ERR | G_IO_HUP | G_IO_IN;
- g_source_add_poll (source, &cb_source->polls[1]);
- }
- cb_source->polls[2].fd = err_fd;
- if (err_fd >= 0) {
- g_assert (cb_source->callbacks.standard_error);
- cb_source->polls[2].events = G_IO_ERR | G_IO_HUP | G_IO_IN;
- g_source_add_poll (source, &cb_source->polls[2]);
- }
-
- if (context == NULL)
- context = g_main_context_default ();
- g_source_set_callback (source, unused_callback, user_data,
- cbs ? cbs->finalize_func : NULL);
- tag = g_source_attach (source, context);
- g_source_unref (source);
-
- return tag;
-}
-
-gboolean
-egg_spawn_sync_with_callbacks (const gchar *working_directory, gchar **argv,
- gchar **envp, GSpawnFlags flags, GPid *child_pid,
- EggSpawnCallbacks *cbs, gpointer user_data,
- gint *exit_status, GError **error)
-{
- gint in_fd, out_fd, err_fd, max_fd;
- fd_set read_fds, write_fds;
- gboolean failed = FALSE;
- gint status;
- GPid pid;
- gint ret;
-
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail ((cbs && cbs->standard_input == NULL) ||
- !(flags & G_SPAWN_CHILD_INHERITS_STDIN), 0);
- g_return_val_if_fail ((cbs && cbs->standard_output == NULL) ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), 0);
- g_return_val_if_fail ((cbs && cbs->standard_error == NULL) ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), 0);
-
- in_fd = out_fd = err_fd = -1;
-
- if (exit_status)
- flags |= G_SPAWN_DO_NOT_REAP_CHILD;
-
- if (!g_spawn_async_with_pipes (working_directory, argv, envp, flags,
- cbs ? cbs->child_setup : NULL,
- user_data, &pid,
- cbs && cbs->standard_input ? &in_fd : NULL,
- cbs && cbs->standard_output ? &out_fd : NULL,
- cbs && cbs->standard_error ? &err_fd : NULL,
- error))
- return FALSE;
-
- if (child_pid)
- *child_pid = pid;
-
- max_fd = MAX (in_fd, MAX (out_fd, err_fd)) + 1;
-
- while (in_fd >= 0 || out_fd >= 0 || err_fd >= 0) {
-
- FD_ZERO (&write_fds);
- if (in_fd >= 0)
- FD_SET (in_fd, &write_fds);
- FD_ZERO (&read_fds);
- if (out_fd >= 0)
- FD_SET (out_fd, &read_fds);
- if (err_fd >= 0)
- FD_SET (err_fd, &read_fds);
-
- ret = select (max_fd, &read_fds, &write_fds, NULL, NULL);
- if (ret < 0 && errno != EINTR) {
- failed = TRUE;
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
- _("Unexpected error in select() reading data from a child process (%s)"),
- g_strerror (errno));
- break;
- }
-
- if (in_fd >= 0 && FD_ISSET (in_fd, &write_fds)) {
- g_assert (cbs && cbs->standard_input);
- if (!(cbs->standard_input) (in_fd, user_data))
- close_fd (&in_fd);
- }
- if (out_fd >= 0 && FD_ISSET (out_fd, &read_fds)) {
- g_assert (cbs && cbs->standard_output);
- if (!(cbs->standard_output) (out_fd, user_data))
- close_fd (&out_fd);
- }
- if (err_fd >= 0 && FD_ISSET (err_fd, &read_fds)) {
- g_assert (cbs && cbs->standard_error);
- if (!(cbs->standard_error) (err_fd, user_data))
- close_fd (&err_fd);
- }
- }
-
- if (in_fd >= 0)
- close_fd (&in_fd);
- if (out_fd >= 0)
- close_fd (&out_fd);
- if (err_fd >= 0)
- close_fd (&err_fd);
-
- if (!failed) {
- if (cbs && cbs->completed)
- (cbs->completed) (user_data);
- }
-
-again:
- ret = waitpid (pid, &status, 0);
- if (ret < 0) {
- if (errno == EINTR)
- goto again;
- else if (errno == ECHILD) {
- if (exit_status)
- g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but SIGCHLD action was set to SIG_IGN and ECHILD was received by waitpid(), so exit status can't be returned. This is a bug in the program calling g_spawn_sync(); either don't request the exit status, or don't set the SIGCHLD action.");
- else
- ; /* We don't need the exit status. */
- } else if (!failed) { /* avoid error pileups */
- failed = TRUE;
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
- _("Unexpected error in waitpid() (%s)"),
- g_strerror (errno));
- }
- } else {
- if (exit_status)
- *exit_status = status;
- }
-
- if (!child_pid)
- g_spawn_close_pid (pid);
-
- if (cbs && cbs->finalize_func)
- (cbs->finalize_func) (user_data);
-
- return !failed;
-}
-
-gssize
-egg_spawn_write_input (int fd, gconstpointer data, gsize n_data)
-{
- gssize result;
-
- g_return_val_if_fail (fd >= 0, -1);
-
- for (;;) {
- result = write (fd, data, n_data);
- if (result < 0) {
- if (errno == EINTR)
- continue;
- else if (errno == EAGAIN)
- result = 0;
- }
- break;
- }
-
- return result;
-}
-
-gssize
-egg_spawn_read_output (int fd, gpointer data, gsize n_data)
-{
- gssize result;
-
- g_return_val_if_fail (fd >= 0, -1);
-
- for (;;) {
- result = read (fd, data, n_data);
- if (result < 0) {
- if (errno == EINTR)
- continue;
- else if (errno == EAGAIN)
- result = 0;
- }
- break;
- }
-
- return result;
-}
-