daemom: for now, ignore clients when they are more than one per app
[ladish.git] / daemon / main.c
blob546abe3e729da19fe049fbd23f8b82b5cdeeafc3
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 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 "../catdup.h"
43 #include "dirhelpers.h"
44 #include "../proxies/a2j_proxy.h"
46 bool g_quit;
47 const char * g_dbus_unique_name;
48 dbus_object_path g_control_object;
49 char * g_base_dir;
51 #if 0
52 static DBusHandlerResult lashd_client_disconnect_handler(DBusConnection * connection, DBusMessage * message, void * data)
54 /* If the message isn't a signal the object path handler may use it */
55 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
57 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
60 const char *member, *name, *old_name;
61 struct lash_client *client;
63 if (!(member = dbus_message_get_member(message)))
65 log_error("Received JACK signal with NULL member");
66 return DBUS_HANDLER_RESULT_HANDLED;
69 if (strcmp(member, "NameOwnerChanged") != 0)
71 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
74 dbus_error_init(&err);
76 if (!dbus_message_get_args(message, &err,
77 DBUS_TYPE_STRING, &name,
78 DBUS_TYPE_STRING, &old_name,
79 DBUS_TYPE_INVALID))
81 log_error("Cannot get message arguments: %s",
82 err.message);
83 dbus_error_free(&err);
84 return DBUS_HANDLER_RESULT_HANDLED;
87 client = server_find_client_by_dbus_name(old_name);
88 if (client)
90 client_disconnected(client);
91 return DBUS_HANDLER_RESULT_HANDLED;
94 else
96 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
100 dbus_bus_add_match(
101 service->connection,
102 "type='signal'"
103 ",sender='org.freedesktop.DBus'"
104 ",path='/org/freedesktop/DBus'"
105 ",interface='org.freedesktop.DBus'"
106 ",member='NameOwnerChanged'"
107 ",arg2=''",
108 &err);
109 if (dbus_error_is_set(&err))
111 log_error("Failed to add D-Bus match rule: %s", err.message);
112 dbus_error_free(&err);
113 goto fail;
116 if (!dbus_connection_add_filter(service->connection, lashd_client_disconnect_handler, NULL, NULL))
118 log_error("Failed to add D-Bus filter");
119 goto fail;
121 #endif
123 static bool connect_dbus(void)
125 int ret;
127 dbus_error_init(&g_dbus_error);
129 g_dbus_connection = dbus_bus_get(DBUS_BUS_SESSION, &g_dbus_error);
130 if (dbus_error_is_set(&g_dbus_error))
132 log_error("Failed to get bus: %s", g_dbus_error.message);
133 dbus_error_free(&g_dbus_error);
134 goto fail;
137 g_dbus_unique_name = dbus_bus_get_unique_name(g_dbus_connection);
138 if (g_dbus_unique_name == NULL)
140 log_error("Failed to read unique bus name");
141 goto unref_connection;
144 log_info("Connected to local session bus, unique name is \"%s\"", g_dbus_unique_name);
146 ret = dbus_bus_request_name(g_dbus_connection, SERVICE_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, &g_dbus_error);
147 if (ret == -1)
149 log_error("Failed to acquire bus name: %s", g_dbus_error.message);
150 dbus_error_free(&g_dbus_error);
151 goto unref_connection;
154 if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
156 log_error("Requested connection name already exists");
157 goto unref_connection;
160 g_control_object = dbus_object_path_new(CONTROL_OBJECT_PATH, &g_lashd_interface_control, NULL, NULL);
161 if (g_control_object == NULL)
163 goto unref_connection;
166 if (!dbus_object_path_register(g_dbus_connection, g_control_object))
168 goto destroy_control_object;
171 return true;
173 destroy_control_object:
174 dbus_object_path_destroy(g_dbus_connection, g_control_object);
175 unref_connection:
176 dbus_connection_unref(g_dbus_connection);
178 fail:
179 return false;
182 static void disconnect_dbus(void)
184 dbus_object_path_destroy(g_dbus_connection, g_control_object);
185 dbus_connection_unref(g_dbus_connection);
188 void term_signal_handler(int signum)
190 log_info("Caught signal %d (%s), terminating", signum, strsignal(signum));
191 g_quit = true;
194 bool install_term_signal_handler(int signum, bool ignore_if_already_ignored)
196 sig_t sigh;
198 sigh = signal(signum, term_signal_handler);
199 if (sigh == SIG_ERR)
201 log_error("signal() failed to install handler function for signal %d.", signum);
202 return false;
205 if (sigh == SIG_IGN && ignore_if_already_ignored)
207 signal(SIGTERM, SIG_IGN);
210 return true;
213 bool init_paths(void)
215 const char * home_dir;
217 home_dir = getenv("HOME");
218 if (home_dir == NULL)
220 log_error("Environment variable HOME not set");
221 return false;
224 g_base_dir = catdup(home_dir, BASE_DIR);
225 if (g_base_dir == NULL)
227 log_error("catdup failed for '%s' and '%s'", home_dir, BASE_DIR);
228 return false;
231 if (!ensure_dir_exist(g_base_dir, 0700))
233 free(g_base_dir);
234 return false;
237 return true;
240 void uninit_paths(void)
242 free(g_base_dir);
245 int main(int argc, char ** argv, char ** envp)
247 struct stat st;
248 char timestamp_str[26];
249 int ret;
251 st.st_mtime = 0;
252 stat(argv[0], &st);
253 ctime_r(&st.st_mtime, timestamp_str);
254 timestamp_str[24] = 0;
256 lash_init_setproctitle(argc, argv, envp);
258 dbus_threads_init_default();
260 log_info("------------------");
261 log_info("LADI session handler activated. Version %s (%s) built on %s", PACKAGE_VERSION, GIT_VERSION, timestamp_str);
263 ret = EXIT_FAILURE;
265 if (!init_paths())
267 goto exit;
270 loader_init(studio_on_child_exit);
272 if (!connect_dbus())
274 log_error("Failed to connecto to D-Bus");
275 goto uninit_loader;
278 /* install the signal handlers */
279 install_term_signal_handler(SIGTERM, false);
280 install_term_signal_handler(SIGINT, true);
281 install_term_signal_handler(SIGHUP, true);
282 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
284 log_error("signal(SIGPIPE, SIG_IGN).");
287 /* setup our SIGSEGV magic that prints nice stack in our logfile */
288 setup_sigsegv();
290 a2j_proxy_init();
292 if (!studio_init())
294 goto uninit_dbus;
297 while (!g_quit)
299 dbus_connection_read_write_dispatch(g_dbus_connection, 50);
300 loader_run();
301 studio_run();
304 ret = EXIT_SUCCESS;
306 log_debug("Finished, cleaning up");
308 studio_uninit();
310 a2j_proxy_uninit();
312 uninit_dbus:
313 disconnect_dbus();
315 uninit_loader:
316 loader_uninit();
318 uninit_paths();
320 exit:
321 log_debug("Cleaned up, exiting");
323 log_info("LADI session handler deactivated");
324 log_info("------------------");
326 exit(EXIT_SUCCESS);