1 /* -*- Mode: C ; c-basic-offset: 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.
35 #include "version.h" /* git version define */
36 #include "proctitle.h"
39 #include "dbus_iface_control.h"
44 const char * g_dbus_unique_name
;
45 object_path_t
* g_control_object
;
46 studio_handle g_studio
;
49 static DBusHandlerResult
lashd_client_disconnect_handler(DBusConnection
* connection
, DBusMessage
* message
, void * data
)
51 /* If the message isn't a signal the object path handler may use it */
52 if (dbus_message_get_type(message
) != DBUS_MESSAGE_TYPE_SIGNAL
)
54 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
57 const char *member
, *name
, *old_name
;
58 struct lash_client
*client
;
61 if (!(member
= dbus_message_get_member(message
)))
63 lash_error("Received JACK signal with NULL member");
64 return DBUS_HANDLER_RESULT_HANDLED
;
67 if (strcmp(member
, "NameOwnerChanged") != 0)
69 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
72 dbus_error_init(&err
);
74 if (!dbus_message_get_args(message
, &err
,
75 DBUS_TYPE_STRING
, &name
,
76 DBUS_TYPE_STRING
, &old_name
,
79 lash_error("Cannot get message arguments: %s",
81 dbus_error_free(&err
);
82 return DBUS_HANDLER_RESULT_HANDLED
;
85 client
= server_find_client_by_dbus_name(old_name
);
88 client_disconnected(client
);
89 return DBUS_HANDLER_RESULT_HANDLED
;
94 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
101 ",sender='org.freedesktop.DBus'"
102 ",path='/org/freedesktop/DBus'"
103 ",interface='org.freedesktop.DBus'"
104 ",member='NameOwnerChanged'"
107 if (dbus_error_is_set(&err
))
109 lash_error("Failed to add D-Bus match rule: %s", err
.message
);
110 dbus_error_free(&err
);
114 if (!dbus_connection_add_filter(service
->connection
, lashd_client_disconnect_handler
, NULL
, NULL
))
116 lash_error("Failed to add D-Bus filter");
121 static bool connect_dbus(void)
125 g_dbus_connection
= dbus_bus_get(DBUS_BUS_SESSION
, &g_dbus_error
);
126 if (dbus_error_is_set(&g_dbus_error
))
128 lash_error("Failed to get bus: %s", g_dbus_error
.message
);
129 dbus_error_free(&g_dbus_error
);
133 g_dbus_unique_name
= dbus_bus_get_unique_name(g_dbus_connection
);
134 if (g_dbus_unique_name
== NULL
)
136 lash_error("Failed to read unique bus name");
137 goto unref_connection
;
140 ret
= dbus_bus_request_name(g_dbus_connection
, DBUS_NAME_BASE
, DBUS_NAME_FLAG_DO_NOT_QUEUE
, &g_dbus_error
);
143 lash_error("Failed to acquire bus name: %s", g_dbus_error
.message
);
144 dbus_error_free(&g_dbus_error
);
145 goto unref_connection
;
148 if (ret
== DBUS_REQUEST_NAME_REPLY_EXISTS
)
150 lash_error("Requested connection name already exists");
151 goto unref_connection
;
154 g_control_object
= object_path_new(CONTROL_OBJECT_PATH
, NULL
, 1, &g_lashd_interface_control
, NULL
);
155 if (g_control_object
== NULL
)
157 goto unref_connection
;
160 if (!object_path_register(g_dbus_connection
, g_control_object
))
162 goto destroy_control_object
;
167 destroy_control_object
:
168 object_path_destroy(g_dbus_connection
, g_control_object
);
170 dbus_connection_unref(g_dbus_connection
);
176 static void disconnect_dbus(void)
178 object_path_destroy(g_dbus_connection
, g_control_object
);
179 dbus_connection_unref(g_dbus_connection
);
182 static void on_child_exit(pid_t pid
)
184 //client_disconnected(server_find_client_by_pid(child_ptr->pid));
187 void term_signal_handler(int signum
)
189 lash_info("Caught signal %d (%s), terminating", signum
, strsignal(signum
));
193 bool install_term_signal_handler(int signum
, bool ignore_if_already_ignored
)
197 sigh
= signal(signum
, term_signal_handler
);
200 lash_error("signal() failed to install handler function for signal %d.", signum
);
204 if (sigh
== SIG_IGN
&& ignore_if_already_ignored
)
206 signal(SIGTERM
, SIG_IGN
);
212 int main(int argc
, char ** argv
, char ** envp
)
215 char timestamp_str
[26];
220 ctime_r(&st
.st_mtime
, timestamp_str
);
221 timestamp_str
[24] = 0;
223 lash_init_setproctitle(argc
, argv
, envp
);
225 dbus_threads_init_default();
227 lash_info("------------------");
228 lash_info("LADI session handler activated. Version %s (%s) built on %s", PACKAGE_VERSION
, GIT_VERSION
, timestamp_str
);
232 loader_init(on_child_exit
);
236 lash_error("Failed to connecto to D-Bus");
240 /* install the signal handlers */
241 install_term_signal_handler(SIGTERM
, false);
242 install_term_signal_handler(SIGINT
, true);
243 install_term_signal_handler(SIGHUP
, true);
244 if (signal(SIGPIPE
, SIG_IGN
) == SIG_ERR
)
246 lash_error("signal(SIGPIPE, SIG_IGN).");
249 /* setup our SIGSEGV magic that prints nice stack in our logfile */
259 dbus_connection_read_write_dispatch(g_dbus_connection
, 50);
263 if (g_studio
!= NULL
)
265 studio_destroy(g_studio
);
266 emit_studio_disappeared();
271 lash_debug("Finished, cleaning up");
281 lash_debug("Cleaned up, exiting");
283 lash_info("LADI session handler deactivated");
284 lash_info("------------------");