waf: fix the include path workaround
[ladish.git] / daemon / main.c
blob14c1393ed98f943512fe3574fa15eaa861172b8c
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari <juuso.alasuutari@gmail.com>
7 * Copyright (C) 2002 Robert Ham <rah@bash.sh>
9 **************************************************************************
10 * This file contains the code that implements main() and other top-level functionality
11 **************************************************************************
13 * LADI Session Handler is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * LADI Session Handler is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
25 * or write to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "common.h"
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <sys/stat.h>
35 #include "version.h" /* git version define */
36 #include "proctitle.h"
37 #include "loader.h"
38 #include "sigsegv.h"
39 #include "control.h"
40 #include "studio.h"
41 #include "../dbus_constants.h"
42 #include "../common/catdup.h"
43 #include "../common/dirhelpers.h"
44 #include "../proxies/a2j_proxy.h"
45 #include "../proxies/jmcore_proxy.h"
46 #include "../proxies/notify_proxy.h"
47 #include "../proxies/conf_proxy.h"
48 #include "conf.h"
49 #include "recent_projects.h"
51 bool g_quit;
52 const char * g_dbus_unique_name;
53 dbus_object_path g_control_object;
54 char * g_base_dir;
55 static bool g_use_notify = false;
57 #if 0
58 static DBusHandlerResult lashd_client_disconnect_handler(DBusConnection * connection, DBusMessage * message, void * data)
60 /* If the message isn't a signal the object path handler may use it */
61 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
63 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
66 const char *member, *name, *old_name;
67 struct lash_client *client;
69 if (!(member = dbus_message_get_member(message)))
71 log_error("Received JACK signal with NULL member");
72 return DBUS_HANDLER_RESULT_HANDLED;
75 if (strcmp(member, "NameOwnerChanged") != 0)
77 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
80 dbus_error_init(&err);
82 if (!dbus_message_get_args(message, &err,
83 DBUS_TYPE_STRING, &name,
84 DBUS_TYPE_STRING, &old_name,
85 DBUS_TYPE_INVALID))
87 log_error("Cannot get message arguments: %s",
88 err.message);
89 dbus_error_free(&err);
90 return DBUS_HANDLER_RESULT_HANDLED;
93 client = server_find_client_by_dbus_name(old_name);
94 if (client)
96 client_disconnected(client);
97 return DBUS_HANDLER_RESULT_HANDLED;
100 else
102 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
106 dbus_bus_add_match(
107 service->connection,
108 "type='signal'"
109 ",sender='org.freedesktop.DBus'"
110 ",path='/org/freedesktop/DBus'"
111 ",interface='org.freedesktop.DBus'"
112 ",member='NameOwnerChanged'"
113 ",arg2=''",
114 &err);
115 if (dbus_error_is_set(&err))
117 log_error("Failed to add D-Bus match rule: %s", err.message);
118 dbus_error_free(&err);
119 goto fail;
122 if (!dbus_connection_add_filter(service->connection, lashd_client_disconnect_handler, NULL, NULL))
124 log_error("Failed to add D-Bus filter");
125 goto fail;
127 #endif
129 static bool connect_dbus(void)
131 int ret;
133 dbus_error_init(&g_dbus_error);
135 g_dbus_connection = dbus_bus_get(DBUS_BUS_SESSION, &g_dbus_error);
136 if (dbus_error_is_set(&g_dbus_error))
138 log_error("Failed to get bus: %s", g_dbus_error.message);
139 dbus_error_free(&g_dbus_error);
140 goto fail;
143 g_dbus_unique_name = dbus_bus_get_unique_name(g_dbus_connection);
144 if (g_dbus_unique_name == NULL)
146 log_error("Failed to read unique bus name");
147 goto unref_connection;
150 log_info("Connected to local session bus, unique name is \"%s\"", g_dbus_unique_name);
152 ret = dbus_bus_request_name(g_dbus_connection, SERVICE_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, &g_dbus_error);
153 if (ret == -1)
155 log_error("Failed to acquire bus name: %s", g_dbus_error.message);
156 dbus_error_free(&g_dbus_error);
157 goto unref_connection;
160 if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
162 log_error("Requested connection name already exists");
163 goto unref_connection;
166 g_control_object = dbus_object_path_new(CONTROL_OBJECT_PATH, &g_lashd_interface_control, NULL, NULL);
167 if (g_control_object == NULL)
169 goto unref_connection;
172 if (!dbus_object_path_register(g_dbus_connection, g_control_object))
174 goto destroy_control_object;
177 return true;
179 destroy_control_object:
180 dbus_object_path_destroy(g_dbus_connection, g_control_object);
181 unref_connection:
182 dbus_connection_unref(g_dbus_connection);
184 fail:
185 return false;
188 static void disconnect_dbus(void)
190 dbus_object_path_destroy(g_dbus_connection, g_control_object);
191 dbus_connection_unref(g_dbus_connection);
194 void term_signal_handler(int signum)
196 log_info("Caught signal %d (%s), terminating", signum, strsignal(signum));
197 g_quit = true;
200 bool install_term_signal_handler(int signum, bool ignore_if_already_ignored)
202 sig_t sigh;
204 sigh = signal(signum, term_signal_handler);
205 if (sigh == SIG_ERR)
207 log_error("signal() failed to install handler function for signal %d.", signum);
208 return false;
211 if (sigh == SIG_IGN && ignore_if_already_ignored)
213 signal(SIGTERM, SIG_IGN);
216 return true;
219 bool init_paths(void)
221 const char * home_dir;
223 home_dir = getenv("HOME");
224 if (home_dir == NULL)
226 log_error("Environment variable HOME not set");
227 return false;
230 g_base_dir = catdup(home_dir, BASE_DIR);
231 if (g_base_dir == NULL)
233 log_error("catdup failed for '%s' and '%s'", home_dir, BASE_DIR);
234 return false;
237 if (!ensure_dir_exist(g_base_dir, 0700))
239 free(g_base_dir);
240 return false;
243 return true;
246 void uninit_paths(void)
248 free(g_base_dir);
251 static void on_conf_notify_changed(void * context, const char * key, const char * value)
253 bool notify_enable;
255 if (value == NULL)
257 notify_enable = LADISH_CONF_KEY_DAEMON_NOTIFY_DEFAULT;
259 else
261 notify_enable = conf_string2bool(value);
264 if (notify_enable)
266 if (!g_use_notify)
268 g_use_notify = ladish_notify_init("LADI Session Handler");
271 else
273 log_info("Sending notifications is disabled");
274 if (g_use_notify)
276 ladish_notify_uninit();
277 g_use_notify = false;
282 int main(int argc, char ** argv, char ** envp)
284 struct stat st;
285 char timestamp_str[26];
286 int ret;
288 st.st_mtime = 0;
289 stat(argv[0], &st);
290 ctime_r(&st.st_mtime, timestamp_str);
291 timestamp_str[24] = 0;
293 lash_init_setproctitle(argc, argv, envp);
295 dbus_threads_init_default();
297 log_info("------------------");
298 log_info("LADI session handler activated. Version %s (%s) built on %s", PACKAGE_VERSION, GIT_VERSION, timestamp_str);
300 ret = EXIT_FAILURE;
302 if (!init_paths())
304 goto exit;
307 loader_init(ladish_studio_on_child_exit);
309 if (!room_templates_init())
311 goto uninit_loader;
314 if (!connect_dbus())
316 log_error("Failed to connecto to D-Bus");
317 goto uninit_room_templates;
320 /* install the signal handlers */
321 install_term_signal_handler(SIGTERM, false);
322 install_term_signal_handler(SIGINT, true);
323 install_term_signal_handler(SIGHUP, true);
324 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
326 log_error("signal(SIGPIPE, SIG_IGN).");
329 /* setup our SIGSEGV magic that prints nice stack in our logfile */
330 setup_sigsegv();
332 if (!conf_proxy_init())
334 goto uninit_dbus;
337 if (!conf_register(LADISH_CONF_KEY_DAEMON_NOTIFY, on_conf_notify_changed, NULL))
339 goto uninit_conf;
342 if (!conf_register(LADISH_CONF_KEY_DAEMON_SHELL, NULL, NULL))
344 goto uninit_conf;
347 if (!conf_register(LADISH_CONF_KEY_DAEMON_TERMINAL, NULL, NULL))
349 goto uninit_conf;
352 if (!conf_register(LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART, NULL, NULL))
354 goto uninit_conf;
357 if (!ladish_recent_projects_init())
359 goto uninit_conf;
362 if (!a2j_proxy_init())
364 goto uninit_recent_projects;
367 if (!jmcore_proxy_init())
369 goto uninit_a2j;
372 if (!ladish_studio_init())
374 goto uninit_jmcore;
377 ladish_notify_simple(LADISH_NOTIFY_URGENCY_LOW, "LADI Session Handler daemon activated", NULL);
379 while (!g_quit)
381 dbus_connection_read_write_dispatch(g_dbus_connection, 50);
382 loader_run();
383 ladish_studio_run();
386 emit_clean_exit();
387 ladish_notify_simple(LADISH_NOTIFY_URGENCY_LOW, "LADI Session Handler daemon deactivated", NULL);
389 ret = EXIT_SUCCESS;
391 log_debug("Finished, cleaning up");
393 ladish_studio_uninit();
395 uninit_jmcore:
396 jmcore_proxy_uninit();
398 uninit_a2j:
399 a2j_proxy_uninit();
401 uninit_recent_projects:
402 ladish_recent_projects_uninit();
404 uninit_conf:
405 if (g_use_notify)
407 ladish_notify_uninit();
410 conf_proxy_uninit();
412 uninit_dbus:
413 disconnect_dbus();
415 uninit_room_templates:
416 room_templates_uninit();
418 uninit_loader:
419 loader_uninit();
421 uninit_paths();
423 exit:
424 log_debug("Cleaned up, exiting");
426 log_info("LADI session handler deactivated");
427 log_info("------------------");
429 exit(EXIT_SUCCESS);