3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/signalfd.h>
37 #define SHUTDOWN_GRACE_SECONDS 10
39 static GMainLoop *event_loop;
41 void __ofono_exit(void)
43 g_main_loop_quit(event_loop);
46 static gboolean quit_eventloop(gpointer user_data)
52 static unsigned int __terminated = 0;
54 static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
57 struct signalfd_siginfo si;
61 if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
64 fd = g_io_channel_unix_get_fd(channel);
66 result = read(fd, &si, sizeof(si));
67 if (result != sizeof(si))
70 switch (si.ssi_signo) {
73 if (__terminated == 0) {
74 ofono_info("Terminating");
75 g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
76 quit_eventloop, NULL);
77 __ofono_modem_shutdown();
87 static guint setup_signalfd(void)
95 sigaddset(&mask, SIGINT);
96 sigaddset(&mask, SIGTERM);
98 if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
99 perror("Failed to set signal mask");
103 fd = signalfd(-1, &mask, 0);
105 perror("Failed to create signal descriptor");
109 channel = g_io_channel_unix_new(fd);
111 g_io_channel_set_close_on_unref(channel, TRUE);
112 g_io_channel_set_encoding(channel, NULL, NULL);
113 g_io_channel_set_buffered(channel, FALSE);
115 source = g_io_add_watch(channel,
116 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
117 signal_handler, NULL);
119 g_io_channel_unref(channel);
124 static void system_bus_disconnected(DBusConnection *conn, void *user_data)
126 ofono_error("System bus has disconnected!");
128 g_main_loop_quit(event_loop);
131 static gchar *option_debug = NULL;
132 static gchar *option_plugin = NULL;
133 static gchar *option_noplugin = NULL;
134 static gboolean option_detach = TRUE;
135 static gboolean option_version = FALSE;
137 static gboolean parse_debug(const char *key, const char *value,
138 gpointer user_data, GError **error)
141 option_debug = g_strdup(value);
143 option_debug = g_strdup("*");
148 static GOptionEntry options[] = {
149 { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
150 G_OPTION_ARG_CALLBACK, parse_debug,
151 "Specify debug options to enable", "DEBUG" },
152 { "plugin", 'p', 0, G_OPTION_ARG_STRING, &option_plugin,
153 "Specify plugins to load", "NAME,..," },
154 { "noplugin", 'P', 0, G_OPTION_ARG_STRING, &option_noplugin,
155 "Specify plugins not to load", "NAME,..." },
156 { "nodetach", 'n', G_OPTION_FLAG_REVERSE,
157 G_OPTION_ARG_NONE, &option_detach,
158 "Don't run as daemon in background" },
159 { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
160 "Show version information and exit" },
164 int main(int argc, char **argv)
166 GOptionContext *context;
168 DBusConnection *conn;
173 if (g_thread_supported() == FALSE)
177 context = g_option_context_new(NULL);
178 g_option_context_add_main_entries(context, options, NULL);
180 if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
182 g_printerr("%s\n", err->message);
187 g_printerr("An unknown error occurred\n");
191 g_option_context_free(context);
193 if (option_version == TRUE) {
194 printf("%s\n", VERSION);
198 if (option_detach == TRUE) {
200 perror("Can't start daemon");
205 event_loop = g_main_loop_new(NULL, FALSE);
208 if (dbus_threads_init_default() == FALSE) {
209 fprintf(stderr, "Can't init usage of threads\n");
214 signal = setup_signalfd();
216 __ofono_log_init(argv[0], option_debug, option_detach);
218 dbus_error_init(&error);
220 conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, OFONO_SERVICE, &error);
222 if (dbus_error_is_set(&error) == TRUE) {
223 ofono_error("Unable to hop onto D-Bus: %s",
225 dbus_error_free(&error);
227 ofono_error("Unable to hop onto D-Bus");
233 g_dbus_set_disconnect_function(conn, system_bus_disconnected,
236 __ofono_dbus_init(conn);
238 __ofono_modemwatch_init();
240 __ofono_manager_init();
242 __ofono_plugin_init(option_plugin, option_noplugin);
244 g_free(option_plugin);
245 g_free(option_noplugin);
247 g_main_loop_run(event_loop);
249 __ofono_plugin_cleanup();
251 __ofono_manager_cleanup();
253 __ofono_modemwatch_cleanup();
255 __ofono_dbus_cleanup();
256 dbus_connection_unref(conn);
259 g_source_remove(signal);
261 g_main_loop_unref(event_loop);
263 __ofono_log_cleanup();