*
* Connection Manager
*
- * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
+ * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#endif
#include <unistd.h>
+#include <stdarg.h>
#include <sys/wait.h>
#include <glib.h>
struct connman_task {
char *path;
pid_t pid;
+ guint child_watch;
GPtrArray *argv;
GPtrArray *envp;
connman_task_exit_t exit_func;
if (task->pid > 0)
kill(task->pid, SIGTERM);
+ if (task->child_watch > 0)
+ g_source_remove(task->child_watch);
+
g_ptr_array_foreach(task->envp, free_pointer, NULL);
g_ptr_array_free(task->envp, TRUE);
}
/**
+ * connman_task_get_path:
+ * @task: task structure
+ *
+ * Get object path
+ */
+const char *connman_task_get_path(struct connman_task *task)
+{
+ return task->path;
+}
+
+/**
* connman_task_add_argument:
* @task: task structure
- * @argument: argument name
- * @value: optional argument value
+ * @name: argument name
+ * @format: format string
+ * @Varargs: list of arguments
*
* Add a new command line argument
*/
int connman_task_add_argument(struct connman_task *task,
- const char *argument, const char *value)
+ const char *name, const char *format, ...)
{
+ va_list ap;
char *str;
- DBG("task %p arg %s val %s", task, argument, value);
+ DBG("task %p arg %s", task, name);
- if (argument == NULL)
+ if (name == NULL)
return -EINVAL;
- str = g_strdup(argument);
+ str = g_strdup(name);
g_ptr_array_add(task->argv, str);
- if (value != NULL) {
- str = g_strdup(value);
+ va_start(ap, format);
+
+ if (format != NULL) {
+ str = g_strdup_vprintf(format, ap);
g_ptr_array_add(task->argv, str);
}
+ va_end(ap);
+
return 0;
}
* connman_task_add_variable:
* @task: task structure
* @key: variable name
- * @value: optional variable value
+ * @format: format string
+ * @Varargs: list of arguments
*
* Add a new environment variable
*/
int connman_task_add_variable(struct connman_task *task,
- const char *key, const char *value)
+ const char *key, const char *format, ...)
{
- char *str;
+ va_list ap;
+ char *str, *val;
- DBG("task %p key %s val %s", task, key, value);
+ DBG("task %p key %s", task, key);
if (key == NULL)
return -EINVAL;
- str = g_strdup_printf("%s=%s", key, value ? value : "");
+ va_start(ap, format);
+
+ val = g_strdup_vprintf(format, ap);
+ str = g_strdup_printf("%s=%s", key, format ? format : "");
g_ptr_array_add(task->envp, str);
+ g_free(val);
+
+ va_end(ap);
return 0;
}
static void task_died(GPid pid, gint status, gpointer user_data)
{
struct connman_task *task = user_data;
+ int exit_code;
- if (WIFEXITED(status))
- DBG("task %p exit status %d", task, WEXITSTATUS(status));
- else
+ if (WIFEXITED(status)) {
+ exit_code = WEXITSTATUS(status);
+ DBG("task %p exit status %d", task, exit_code);
+ } else {
+ exit_code = 0;
DBG("task %p signal %d", task, WTERMSIG(status));
+ }
g_spawn_close_pid(pid);
task->pid = -1;
+ task->child_watch = 0;
+
if (task->exit_func)
- task->exit_func(task, task->exit_data);
+ task->exit_func(task, exit_code, task->exit_data);
}
static void task_setup(gpointer user_data)
* @task: task structure
* @function: exit callback
* @user_data: optional exit user data
+ * @fd: optional spawn with pipe
*
* Execute program specified by #task
*/
int connman_task_run(struct connman_task *task,
- connman_task_exit_t function, void *user_data)
+ connman_task_exit_t function, void *user_data,
+ int *stdin_fd, int *stdout_fd, int *stderr_fd)
{
- GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD |
- G_SPAWN_STDOUT_TO_DEV_NULL;
+ GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD;
+ gboolean result;
char **argv, **envp;
DBG("task %p", task);
if (task->pid > 0)
return -EALREADY;
+ if (stdout_fd == NULL)
+ flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
+
+ if (stderr_fd == NULL)
+ flags |= G_SPAWN_STDERR_TO_DEV_NULL;
+
task->exit_func = function;
task->exit_data = user_data;
argv = (char **) task->argv->pdata;
envp = (char **) task->envp->pdata;
- if (g_spawn_async(NULL, argv, envp, flags,
- task_setup, task, &task->pid, NULL) == FALSE) {
+ result = g_spawn_async_with_pipes(NULL, argv, envp, flags,
+ task_setup, task, &task->pid,
+ stdin_fd, stdout_fd, stderr_fd, NULL);
+ if (result == FALSE) {
connman_error("Failed to spawn %s", argv[0]);
return -EIO;
}
- g_child_watch_add(task->pid, task_died, task);
+ task->child_watch = g_child_watch_add(task->pid, task_died, task);
return 0;
}
if (dbus_message_get_no_reply(message) == FALSE) {
DBusMessage *reply;
- dbus_bool_t result;
reply = dbus_message_new_method_return(message);
if (reply == NULL)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
- result = dbus_connection_send(connection, reply, NULL);
+ dbus_connection_send(connection, reply, NULL);
dbus_message_unref(reply);
}