/*
* Copyright (C) 2010-2011 Robert Ancell.
* Author: Robert Ancell <robert.ancell@canonical.com>
- *
+ *
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
#include <fcntl.h>
#include <signal.h>
#include <grp.h>
-#include <glib/gstdio.h>
#include <config.h>
+#include "log-file.h"
#include "process.h"
enum {
GOT_DATA,
- GOT_SIGNAL,
+ GOT_SIGNAL,
STOPPED,
LAST_SIGNAL
};
/* File to log to */
gchar *log_file;
gboolean log_stdout;
+ LogMode log_mode;
/* Command to run */
gchar *command;
/* Process ID */
GPid pid;
-
+
/* Exit status of process */
int exit_status;
Process *process = g_object_new (PROCESS_TYPE, NULL);
process->priv->run_func = run_func;
process->priv->run_func_data = run_func_data;
+ process->priv->log_mode = LOG_MODE_INVALID;
return process;
}
void
-process_set_log_file (Process *process, const gchar *path, gboolean log_stdout)
+process_set_log_file (Process *process, const gchar *path, gboolean log_stdout, LogMode log_mode)
{
g_return_if_fail (process != NULL);
g_free (process->priv->log_file);
process->priv->log_file = g_strdup (path);
process->priv->log_stdout = log_stdout;
+ process->priv->log_mode = log_mode;
}
void
{
g_return_if_fail (process != NULL);
g_return_if_fail (name != NULL);
- g_hash_table_insert (process->priv->env, g_strdup (name), g_strdup (value));
+ g_hash_table_insert (process->priv->env, g_strdup (name), g_strdup (value));
}
const gchar *
if (process->priv->quit_timeout)
g_source_remove (process->priv->quit_timeout);
- process->priv->quit_timeout = 0;
+ process->priv->quit_timeout = 0;
process->priv->pid = 0;
g_hash_table_remove (processes, GINT_TO_POINTER (pid));
gchar **argv;
gchar **env_keys, **env_values;
guint i, env_length;
+ GList *keys, *link;
pid_t pid;
int log_fd = -1;
GError *error = NULL;
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->command != NULL, FALSE);
g_return_val_if_fail (process->priv->pid == 0, FALSE);
if (!g_shell_parse_argv (process->priv->command, &argc, &argv, &error))
}
if (process->priv->log_file)
- {
- gchar *old_filename;
-
- /* Move old file out of the way */
- old_filename = g_strdup_printf ("%s.old", process->priv->log_file);
- rename (process->priv->log_file, old_filename);
- g_free (old_filename);
-
- /* Create new file and log to it */
- log_fd = g_open (process->priv->log_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (log_fd < 0)
- g_warning ("Failed to open log file %s: %s", process->priv->log_file, g_strerror (errno));
- }
+ log_fd = log_file_open (process->priv->log_file, process->priv->log_mode);
/* Work out variables to set */
- env_keys = (gchar **) g_hash_table_get_keys_as_array (process->priv->env, &env_length);
+ env_length = g_hash_table_size (process->priv->env);
+ env_keys = g_malloc (sizeof (gchar *) * env_length);
env_values = g_malloc (sizeof (gchar *) * env_length);
- for (i = 0; i < env_length; i++)
+ keys = g_hash_table_get_keys (process->priv->env);
+ for (i = 0, link = keys; i < env_length; i++, link = link->next)
+ {
+ env_keys[i] = link->data;
env_values[i] = g_hash_table_lookup (process->priv->env, env_keys[i]);
+ }
+ g_list_free (keys);
pid = fork ();
if (pid == 0)
#endif
for (i = 0; i < env_length; i++)
setenv (env_keys[i], env_values[i], TRUE);
-
+
+ /* Reset SIGPIPE handler so the child has default behaviour (we disabled it at LightDM start) */
+ signal (SIGPIPE, SIG_DFL);
+
execvp (argv[0], argv);
_exit (EXIT_FAILURE);
}
-
+
close (log_fd);
g_strfreev (argv);
g_free (env_keys);
int exit_status;
waitpid (process->priv->pid, &exit_status, 0);
process_watch_cb (process->priv->pid, exit_status, process);
- }
+ }
else
{
g_hash_table_insert (processes, GINT_TO_POINTER (process->priv->pid), g_object_ref (process));
static void
process_finalize (GObject *object)
{
- Process *self;
-
- self = PROCESS (object);
+ Process *self = PROCESS (object);
if (self->priv->pid > 0)
g_hash_table_remove (processes, GINT_TO_POINTER (self->priv->pid));
Process *process;
errno = 0;
- if (read (signal_pipe[0], &signo, sizeof (int)) != sizeof (int) ||
+ if (read (signal_pipe[0], &signo, sizeof (int)) != sizeof (int) ||
read (signal_pipe[0], &pid, sizeof (pid_t)) != sizeof (pid_t))
{
g_warning ("Error reading from signal pipe: %s", strerror (errno));
struct sigaction action;
klass->stopped = process_stopped;
- object_class->finalize = process_finalize;
+ object_class->finalize = process_finalize;
g_type_class_add_private (klass, sizeof (ProcessPrivate));
signals[GOT_DATA] =
- g_signal_new ("got-data",
+ g_signal_new (PROCESS_SIGNAL_GOT_DATA,
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ProcessClass, got_data),
NULL, NULL,
NULL,
- G_TYPE_NONE, 0);
+ G_TYPE_NONE, 0);
signals[GOT_SIGNAL] =
- g_signal_new ("got-signal",
+ g_signal_new (PROCESS_SIGNAL_GOT_SIGNAL,
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ProcessClass, got_signal),
NULL,
G_TYPE_NONE, 1, G_TYPE_INT);
signals[STOPPED] =
- g_signal_new ("stopped",
+ g_signal_new (PROCESS_SIGNAL_STOPPED,
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ProcessClass, stopped),