summaryrefslogtreecommitdiff
path: root/src/process.c
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2011-09-11 15:45:10 +1000
committerRobert Ancell <robert.ancell@canonical.com>2011-09-11 15:45:10 +1000
commit42db614c0978158213736bd8dd3d03357fd3743f (patch)
tree32a32fdc33d9e31fa7299e6ad633ee9881f3a542 /src/process.c
parent651763363a183040fd74fde150319fb9d795e278 (diff)
downloadlightdm-42db614c0978158213736bd8dd3d03357fd3743f.tar.gz
Add VNC server support
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c145
1 files changed, 103 insertions, 42 deletions
diff --git a/src/process.c b/src/process.c
index 845bafc7..e4e93147 100644
--- a/src/process.c
+++ b/src/process.c
@@ -22,6 +22,7 @@
#include "process.h"
enum {
+ RUN,
STARTED,
GOT_DATA,
GOT_SIGNAL,
@@ -37,17 +38,23 @@ struct ProcessPrivate
/* Environment variables */
GHashTable *env;
+ /* Command to run */
+ gchar *command;
+
+ /* Working directory */
+ gchar *working_directory;
+
/* User to run as */
User *user;
/* Path of file to log to */
- gchar *log_file;
-
- /* Timeout waiting for process to quit */
- guint quit_timeout;
-
+ gchar *log_file;
+
/* Process ID */
GPid pid;
+
+ /* Timeout waiting for process to quit */
+ guint quit_timeout;
};
G_DEFINE_TYPE (Process, process, G_TYPE_OBJECT);
@@ -75,6 +82,22 @@ process_new (void)
}
void
+process_set_command (Process *process, const gchar *command)
+{
+ g_return_if_fail (process != NULL);
+
+ g_free (process->priv->command);
+ process->priv->command = g_strdup (command);
+}
+
+const gchar *
+process_get_command (Process *process)
+{
+ g_return_val_if_fail (process != NULL, NULL);
+ return process->priv->command;
+}
+
+void
process_set_log_file (Process *process, const gchar *log_file)
{
g_return_if_fail (process != NULL);
@@ -89,7 +112,40 @@ process_get_log_file (Process *process)
g_return_val_if_fail (process != NULL, NULL);
return process->priv->log_file;
}
-
+
+void
+process_set_working_directory (Process *process, const gchar *working_directory)
+{
+ g_return_if_fail (process != NULL);
+
+ g_free (process->priv->working_directory);
+ process->priv->working_directory = g_strdup (working_directory);
+}
+
+const gchar *
+process_get_working_directory (Process *process)
+{
+ g_return_val_if_fail (process != NULL, NULL);
+ return process->priv->working_directory;
+}
+
+void
+process_set_user (Process *process, User *user)
+{
+ g_return_if_fail (process != NULL);
+
+ if (process->priv->user)
+ g_object_unref (process->priv->user);
+ process->priv->user = g_object_ref (user);
+}
+
+User *
+process_get_user (Process *process)
+{
+ g_return_val_if_fail (process != NULL, NULL);
+ return process->priv->user;
+}
+
void
process_set_env (Process *process, const gchar *name, const gchar *value)
{
@@ -130,30 +186,39 @@ process_watch_cb (GPid pid, gint status, gpointer data)
}
static void
-run_process (Process *process, char *const argv[])
+process_run (Process *process)
+{
+ gint argc;
+ gchar **argv;
+ GError *error = NULL;
+
+ if (!g_shell_parse_argv (process->priv->command, &argc, &argv, &error))
+ {
+ g_warning ("Error parsing command %s: %s", process->priv->command, error->message);
+ _exit (EXIT_FAILURE);
+ }
+
+ execv (argv[0], argv);
+
+ g_warning ("Error executing child process %s: %s", argv[0], g_strerror (errno));
+ _exit (EXIT_FAILURE);
+}
+
+static void
+run (Process *process)
{
GHashTableIter iter;
gpointer key, value;
- int fd;
/* FIXME: Close existing file descriptors */
- /* Make input non-blocking */
- fd = g_open ("/dev/null", O_RDONLY);
- dup2 (fd, STDIN_FILENO);
- close (fd);
-
/* Set environment */
clearenv ();
g_hash_table_iter_init (&iter, process->priv->env);
while (g_hash_table_iter_next (&iter, &key, &value))
g_setenv ((gchar *)key, (gchar *)value, TRUE);
- /* Set SIGUSR1 to ignore so the child process can indicate it when it is ready */
- // FIXME: Should be in the xserver only
- signal (SIGUSR1, SIG_IGN);
-
- /* Make this process its own session so */
+ /* Make this process its own session */
if (setsid () < 0)
g_warning ("Failed to make process a new session: %s", strerror (errno));
@@ -203,32 +268,21 @@ run_process (Process *process, char *const argv[])
}
}
- execv (argv[0], argv);
-
- g_warning ("Error executing child process %s: %s", argv[0], g_strerror (errno));
- _exit (EXIT_FAILURE);
+ g_signal_emit (process, signals[RUN], 0);
}
gboolean
-process_start (Process *process,
- User *user,
- const gchar *working_dir,
- const gchar *command,
- GError **error)
+process_start (Process *process)
{
- gboolean result;
- gint argc;
- gchar **argv;
GString *string;
gpointer key, value;
GHashTableIter iter;
pid_t pid;
g_return_val_if_fail (process != NULL, FALSE);
+ g_return_val_if_fail (process->priv->command != NULL, FALSE);
g_return_val_if_fail (process->priv->pid == 0, FALSE);
- process->priv->user = g_object_ref (user);
-
/* Create the log file owned by the target user */
if (process->priv->log_file)
{
@@ -238,10 +292,6 @@ process_start (Process *process,
g_warning ("Failed to set process log file ownership: %s", strerror (errno));
}
- result = g_shell_parse_argv (command, &argc, &argv, error);
- if (!result)
- return FALSE;
-
pid = fork ();
if (pid < 0)
{
@@ -250,14 +300,13 @@ process_start (Process *process,
}
if (pid == 0)
- run_process (process, argv);
- g_strfreev (argv);
+ run (process);
string = g_string_new ("");
g_hash_table_iter_init (&iter, process->priv->env);
while (g_hash_table_iter_next (&iter, &key, &value))
g_string_append_printf (string, "%s=%s ", (gchar *)key, (gchar *)value);
- g_string_append (string, command);
+ g_string_append (string, process->priv->command);
g_debug ("Launching process %d: %s", pid, string->str);
g_string_free (string, TRUE);
@@ -334,12 +383,15 @@ process_finalize (GObject *object)
self = PROCESS (object);
- if (self->priv->user)
- g_object_unref (self->priv->user);
-
if (self->priv->pid > 0)
g_hash_table_remove (processes, GINT_TO_POINTER (self->priv->pid));
+ g_free (self->priv->command);
+ g_free (self->priv->working_directory);
+ g_free (self->priv->log_file);
+ if (self->priv->user)
+ g_object_unref (self->priv->user);
+
if (self->priv->pid)
kill (self->priv->pid, SIGTERM);
@@ -388,11 +440,20 @@ process_class_init (ProcessClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
struct sigaction action;
+ klass->run = process_run;
klass->stopped = process_stopped;
object_class->finalize = process_finalize;
g_type_class_add_private (klass, sizeof (ProcessPrivate));
+ signals[RUN] =
+ g_signal_new ("run",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ProcessClass, run),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
signals[STARTED] =
g_signal_new ("started",
G_TYPE_FROM_CLASS (klass),