Don't try to catch SIGKILL
[tilda-gobject.git] / tilda.c
1 #include <glib.h>
2 #include <stdlib.h>
3 #include <signal.h>
4
5 #include "tilda.h"
6 #include "tilda-window.h"
7 #include "tilda-terminal.h"
8 #include "tomboykeybinder.h"
9
10 DBusGConnection *dbus_connection;
11 GPtrArray *windows;
12
13 static void
14 tilda_initialize_dbus ()
15 {
16         debug_enter  ();
17
18         static const gchar service_name[] = "net.sourceforge.Tilda";
19         GError *error = NULL;
20         DBusGProxy *driver_proxy;
21         guint request_ret;
22         gboolean ret;
23
24         // Initialize the DBus connection
25         dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
26         if (dbus_connection == NULL)
27         {
28                 g_warning (_("Unable to connect to DBus: %s\n"), error->message);
29                 g_error_free (error);
30                 return;
31         }
32
33         // Register the service name
34         driver_proxy = dbus_g_proxy_new_for_name (dbus_connection,
35                                                                                           DBUS_SERVICE_DBUS,
36                                                                                           DBUS_PATH_DBUS,
37                                                                                           DBUS_INTERFACE_DBUS);
38
39         ret = org_freedesktop_DBus_request_name (driver_proxy,
40                                                                                          service_name,
41                                                                                          DBUS_NAME_FLAG_DO_NOT_QUEUE,
42                                                                                          &request_ret,
43                                                                                          &error);
44
45         if (!ret)
46         {
47                 g_warning (_("Unable to communicate with DBus: %s\n"), error->message);
48                 g_error_free (error);
49         }
50
51         if (request_ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
52         {
53                 g_critical (_("There is already an instance of Tilda running\n"));
54                 exit (EXIT_FAILURE);
55         }
56
57         g_object_unref (driver_proxy);
58 }
59
60 static gint
61 tilda_find_next_free_window_number ()
62 {
63         debug_enter  ();
64
65         gint i, j;
66         gboolean found;
67
68         for (i=0; i<INT_MAX; ++i)
69         {
70                 found = FALSE;
71
72                 for (j=0; j<windows->len; ++j)
73                 {
74                         TildaWindow *tw = g_ptr_array_index (windows, j);
75
76                         if (tw->number == i)
77                         {
78                                 found = TRUE;
79                                 break;
80                         }
81                 }
82
83                 if (!found)
84                         return i;
85         }
86
87         return 0;
88 }
89
90 static TildaWindow *
91 tilda_add_window ()
92 {
93         debug_enter ();
94
95         TildaWindow *ret;
96         gint number;
97
98         number = tilda_find_next_free_window_number ();
99         ret = g_object_new (TILDA_TYPE_WINDOW, "number", number, NULL);
100
101         g_ptr_array_add (windows, ret);
102
103         debug_printf ("Adding window: 0x%x (number %d of %d)\n", ret, ret->number, windows->len-1);
104         return ret;
105 }
106
107 void
108 tilda_del_window (gint number)
109 {
110         debug_enter ();
111
112         gint i;
113         TildaWindow *win;
114
115         for (i=0; i<windows->len; ++i)
116         {
117                 win = g_ptr_array_index (windows, i);
118
119                 if (win->number == number)
120                 {
121                         debug_printf ("Deleting window 0x%x (number %d of %d)\n", win, win->number, windows->len-1);
122                         g_ptr_array_remove_index (windows, i);
123                         g_object_unref (G_OBJECT(win));
124
125                         if (windows->len == 0)
126                         {
127                                 debug_printf ("No windows left, exiting...\n");
128                                 gtk_main_quit ();
129                         }
130
131                         break;
132                 }
133         }
134 }
135
136 static void
137 tilda_parse_command_line (gint argc, gchar *argv[])
138 {
139         debug_enter ();
140
141         gboolean version = FALSE;
142
143         /* All of the various command-line options */
144         const GOptionEntry cl_opts[] = {
145                 { "version",                    'V', 0, G_OPTION_ARG_NONE,              &version,                       N_("Show version information"), NULL },
146                 { NULL },
147         };
148
149         /* Set up the command-line parser */
150         GError *error = NULL;
151         GOptionContext *context = g_option_context_new (NULL);
152         g_option_context_add_main_entries (context, cl_opts, NULL);
153         g_option_context_add_group (context, gtk_get_option_group (TRUE));
154         g_option_context_parse (context, &argc, &argv, &error);
155         g_option_context_free (context);
156
157         /* Check for unknown options, and give a nice message if there are some */
158         if (error)
159         {
160                 g_printerr (_("Error parsing command-line options: %s\n"), error->message);
161                 g_printerr (_("The command \"tilda --help\" will show all possible options\n"));
162                 g_error_free (error);
163                 exit (EXIT_FAILURE);
164         }
165
166         /* If we need to show the version, show it then exit normally */
167         if (version)
168         {
169                 g_print ("%s\n\n", TILDA_VERSION);
170
171                 g_print ("Copyright (c) 2005-2008 Tristan Sloughter (sloutri@iit.edu)\n");
172                 g_print ("Copyright (c) 2005-2008 Ira W. Snyder (tilda@irasnyder.com)\n\n");
173
174                 g_print ("This program comes with ABSOLUTELY NO WARRANTY.\n");
175                 g_print ("This is free software, and you are welcome to redistribute it\n");
176                 g_print ("under certain conditions. See the file COPYING for details.\n");
177
178                 exit (EXIT_SUCCESS);
179         }
180 }
181
182 static void
183 tilda_termination_handler (gint signum)
184 {
185         debug_enter  ();
186         debug_printf ("signum: %d\n", signum);
187
188         gtk_main_quit ();
189 }
190
191 /* Hook up all system signal handlers */
192 static void
193 tilda_signal_handlers_init ()
194 {
195         struct sigaction sa;
196
197         /* Hook up signal handlers */
198         sa.sa_handler = tilda_termination_handler;
199         sigemptyset (&sa.sa_mask);
200         sa.sa_flags = 0;
201
202         sigaction (SIGINT,  &sa, NULL);
203         sigaction (SIGQUIT, &sa, NULL);
204         sigaction (SIGABRT, &sa, NULL);
205         sigaction (SIGTERM, &sa, NULL);
206
207         /* SIGKILL cannot be caught according to sigaction(2) and signal(7) */
208         /* sigaction (SIGKILL, &sa, NULL); */
209 }
210
211 int main (int argc, char *argv[])
212 {
213         debug_enter ();
214
215         TildaWindow *tw;
216
217 #if ENABLE_NLS
218         /* Gettext Initialization */
219         setlocale (LC_ALL, "");
220         bindtextdomain (PACKAGE, LOCALEDIR);
221         textdomain (PACKAGE);
222 #endif
223
224         /* Parse the command-line options */
225         tilda_parse_command_line (argc, argv);
226
227         /* Initialize GTK+ (and the GObject system) */
228         gtk_init (&argc, &argv);
229
230         /* Hook up the signal handlers */
231         tilda_signal_handlers_init ();
232
233         /* Initialize the keybinder */
234         tomboy_keybinder_init ();
235
236         /* Start our connection to DBus */
237         tilda_initialize_dbus ();
238
239         /* Initialize the array of windows */
240         windows = g_ptr_array_new ();
241
242         /* Create a TildaWindow, run it, and exit when it does, basically.
243          *
244          * This is nothing like what the real main() will be, but it's
245          * a good start for testing and integration of more of TildaWindow
246          * and TildaTerminal. */
247         tw = tilda_add_window ();
248
249         debug_printf ("Starting gtk_main()!\n");
250         gtk_main ();
251         debug_printf ("Out of gtk_main(), going down\n");
252
253         /* Free the pointer array we allocated earlier */
254         g_ptr_array_free (windows, TRUE);
255
256         return 0;
257 }
258
259 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */