3b82e3c1 |
1 | /* |
2 | * Copyright (c) 2014 Ian Sutton <ian@kremlin.cc> |
3 | * |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | |
5b005882 |
17 | #include <unistd.h> |
18 | #include <limits.h> |
c12c41f4 |
19 | #include <signal.h> |
5b005882 |
20 | |
b6ad18ad |
21 | #include <sys/param.h> |
22 | #include <string.h> |
23 | |
4c04b514 |
24 | #include <glib/gprintf.h> |
8caf1f61 |
25 | #include <glib-unix.h> |
904d744d |
26 | #include <polkit/polkit.h> |
4c04b514 |
27 | |
1e8c7c88 |
28 | #include "localed-gen.h" |
a33bcdfa |
29 | #include "localed.h" |
5b005882 |
30 | |
ed4cf3c8 |
31 | #include "../../util.h" |
483e90b7 |
32 | |
b6ad18ad |
33 | GPtrArray *localed_freeable; |
34 | Locale1 *localed_interf; |
35 | |
c12c41f4 |
36 | GMainLoop *localed_loop; |
37 | |
38 | guint bus_descriptor; |
39 | gboolean dbus_interface_exported; /* reliable because of gdbus operational guarantees */ |
40 | |
1ce41045 |
41 | /* --- begin method/property/dbus signal code --- */ |
b6ad18ad |
42 | |
7279ffec |
43 | static gboolean |
44 | on_handle_set_locale(Locale1 *hn1_passed_interf, |
45 | GDBusMethodInvocation *invoc, |
46 | const gchar *greet, |
47 | gpointer data) { |
b6ad18ad |
48 | return FALSE; |
49 | } |
50 | |
7279ffec |
51 | static gboolean |
52 | on_handle_set_v_console_keyboard(Locale1 *hn1_passed_interf, |
53 | GDBusMethodInvocation *invoc, |
54 | const gchar *greet, |
55 | gpointer data) { |
56 | return FALSE; |
57 | } |
58 | |
59 | static gboolean |
60 | on_handle_set_x11_keyboard(Locale1 *hn1_passed_interf, |
61 | GDBusMethodInvocation *invoc, |
62 | const gchar *greet, |
63 | gpointer data) { |
64 | return FALSE; |
65 | } |
66 | |
67 | const gchar * const * |
68 | our_get_locale() { |
69 | |
70 | const gchar * const *ret = NULL; |
71 | |
72 | return ret; |
73 | } |
74 | |
b6ad18ad |
75 | const gchar * |
7279ffec |
76 | our_get_v_console_keymap() { |
77 | |
78 | return ""; |
79 | } |
80 | |
81 | const gchar * |
82 | our_get_v_console_keymap_toggle() { |
83 | |
84 | return ""; |
85 | } |
b6ad18ad |
86 | |
7279ffec |
87 | const gchar * |
88 | our_get_x11_layout() { |
89 | |
90 | return ""; |
91 | } |
b6ad18ad |
92 | |
7279ffec |
93 | const gchar * |
94 | our_get_x11_model() { |
95 | |
96 | return ""; |
97 | } |
b6ad18ad |
98 | |
7279ffec |
99 | const gchar * |
100 | our_get_x11_variant() { |
101 | |
102 | return ""; |
103 | } |
b6ad18ad |
104 | |
7279ffec |
105 | const gchar * |
106 | our_get_x11_options() { |
107 | |
108 | return ""; |
109 | } |
b6ad18ad |
110 | |
b6ad18ad |
111 | |
1ce41045 |
112 | /* --- end method/property/dbus signal code, begin bus/name handlers --- */ |
b6ad18ad |
113 | |
114 | static void localed_on_bus_acquired(GDBusConnection *conn, |
115 | const gchar *name, |
116 | gpointer user_data) { |
117 | |
254ceec0 |
118 | g_printf("got bus/name, exporting %s's interface...\n", name); |
509599f0 |
119 | |
b6ad18ad |
120 | localed_interf = locale1_skeleton_new(); |
121 | |
7279ffec |
122 | /* attach function pointers to generated struct's method handlers */ |
123 | g_signal_connect(localed_interf, "handle-set-locale", G_CALLBACK(on_handle_set_locale), NULL); |
124 | g_signal_connect(localed_interf, "handle-set-vconsole-keyboard", G_CALLBACK(on_handle_set_v_console_keyboard), NULL); |
125 | g_signal_connect(localed_interf, "handle-set-x11-keyboard", G_CALLBACK(on_handle_set_x11_keyboard), NULL); |
126 | |
127 | /* set our properties before export */ |
128 | locale1_set_locale(localed_interf, our_get_locale()); |
129 | locale1_set_vconsole_keymap(localed_interf, our_get_v_console_keymap()); |
130 | locale1_set_vconsole_keymap_toggle(localed_interf, our_get_v_console_keymap_toggle()); |
131 | locale1_set_x11_layout(localed_interf, our_get_x11_layout()); |
132 | locale1_set_x11_model(localed_interf, our_get_x11_model()); |
133 | locale1_set_x11_variant(localed_interf, our_get_x11_variant()); |
134 | locale1_set_x11_options(localed_interf, our_get_x11_options()); |
b6ad18ad |
135 | |
b6ad18ad |
136 | if(!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(localed_interf), |
137 | conn, |
138 | "/org/freedesktop/locale1", |
139 | NULL)) { |
140 | |
509599f0 |
141 | g_printf("failed to export %s's interface!\n", name); |
142 | localed_mem_clean(); |
143 | |
144 | } else { |
145 | |
146 | dbus_interface_exported = TRUE; |
147 | g_printf("exported %s's interface on the system bus...\n", name); |
b6ad18ad |
148 | } |
509599f0 |
149 | } |
b6ad18ad |
150 | |
509599f0 |
151 | static void localed_on_name_acquired(GDBusConnection *conn, |
90f54407 |
152 | const gchar *name, |
509599f0 |
153 | gpointer user_data) { |
154 | |
90f54407 |
155 | g_printf("success!\n"); |
b6ad18ad |
156 | } |
157 | |
b6ad18ad |
158 | static void localed_on_name_lost(GDBusConnection *conn, |
159 | const gchar *name, |
160 | gpointer user_data) { |
161 | |
90f54407 |
162 | if(!conn) { |
b6ad18ad |
163 | |
90f54407 |
164 | g_printf("failed to connect to the system bus while trying to acquire name '%s': either dbus-daemon isn't running or we don't have permission to push names and/or their interfaces to it.\n", name); |
165 | localed_mem_clean(); |
166 | } |
b6ad18ad |
167 | |
90f54407 |
168 | g_print("lost name %s, exiting...\n", name); |
509599f0 |
169 | |
170 | localed_mem_clean(); |
b6ad18ad |
171 | } |
172 | |
b70beb08 |
173 | /* --- end bus/name handlers, begin misc unix functions --- */ |
174 | |
509599f0 |
175 | /* safe call to clean and then exit |
176 | * this stops our GMainLoop safely before letting main() return */ |
b70beb08 |
177 | void localed_mem_clean() { |
178 | |
90f54407 |
179 | g_printf("exiting...\n"); |
341587db |
180 | |
90f54407 |
181 | if(dbus_interface_exported) |
182 | g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(localed_interf)); |
341587db |
183 | |
90f54407 |
184 | if(g_main_loop_is_running(localed_loop)) |
185 | g_main_loop_quit(localed_loop); |
341587db |
186 | |
b70beb08 |
187 | } |
188 | |
712eb329 |
189 | /* wrapper for glib's unix signal handling; called only once if terminating signal is raised against us */ |
190 | gboolean unix_sig_terminate_handler(gpointer data) { |
191 | |
90f54407 |
192 | g_printf("caught SIGINT/HUP/TERM, exiting\n"); |
712eb329 |
193 | |
90f54407 |
194 | localed_mem_clean(); |
195 | return G_SOURCE_REMOVE; |
712eb329 |
196 | } |
197 | |
2ef2cfe1 |
198 | void set_signal_handlers() { |
199 | |
200 | /* we don't care about its descriptor, we never need to unregister these */ |
201 | g_unix_signal_add(SIGINT, unix_sig_terminate_handler, NULL); |
202 | g_unix_signal_add(SIGHUP, unix_sig_terminate_handler, NULL); |
203 | g_unix_signal_add(SIGTERM, unix_sig_terminate_handler, NULL); |
204 | } |
205 | |
1e8c7c88 |
206 | int main() { |
b6ad18ad |
207 | |
90f54407 |
208 | set_signal_handlers(); |
9728ae1f |
209 | |
90f54407 |
210 | localed_loop = g_main_loop_new(NULL, TRUE); |
211 | localed_freeable = g_ptr_array_new(); |
b6ad18ad |
212 | |
90f54407 |
213 | bus_descriptor = g_bus_own_name(G_BUS_TYPE_SYSTEM, |
b6ad18ad |
214 | "org.freedesktop.locale1", |
215 | G_BUS_NAME_OWNER_FLAGS_NONE, |
216 | localed_on_bus_acquired, |
217 | localed_on_name_acquired, |
218 | localed_on_name_lost, |
219 | NULL, |
220 | NULL); |
221 | |
90f54407 |
222 | g_main_loop_run(localed_loop); |
223 | /* runs until single g_main_loop_quit() call is raised inside <interface>_mem_clean() */ |
224 | g_main_loop_unref(localed_loop); |
b6ad18ad |
225 | |
90f54407 |
226 | /* guaranteed unownable */ |
227 | g_bus_unown_name(bus_descriptor); |
b6ad18ad |
228 | |
90f54407 |
229 | /* at this point no operations can occur with our data, it is safe to free it + its container */ |
230 | g_ptr_array_free(localed_freeable, TRUE); |
b6ad18ad |
231 | |
90f54407 |
232 | return 0; |
5b005882 |
233 | } |