1 #define _DEFAULT_SOURCE
2 /*
3  * This is free software; you can redistribute it and/or modify it under
4  * the terms of the GNU Library General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU Library General Public
14  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
15  */
16 #include <fcntl.h>
17 #define _POSIX_SOURCE /* feature test macro for signal functions */
18 #define _XOPEN_SOURCE /* feature test macro for popen */
19 
20 /*
21  * This message is shown in a modal dialog when tilda starts and there is a problem parsing the configuration file.
22  * Such problems can occur for example if the config file contains a key-value pair that is unknown to tilda. This
23  * can be the case if the user manually modified the configuration file or if a newer version of tilda was run and
24  * which saved some settings that are not known by older versions of tilda.
25  */
26 #define TILDA_CONFIG_PARSE_ERROR \
27     "<b>A problem occurred while parsing the config file.</b>\n\n" \
28     "This can happen if the tilda config contains a setting that is unknown to tilda. " \
29     "Tilda will now start with the default configuration."
30 
31 /*
32  * This message is shown in a modal dialog when tilda starts and there is a any other problem with the configuration
33  * file except a parse error.
34  */
35 #define TILDA_CONFIG_OTHER_ERROR \
36     "<b>An unexpected error occurred while parsing the config file.</b>\n\n" \
37     "The default configuration will be used instead. This error can occur if the configuration file is corrupted" \
38     "or otherwise unreadable. Tilda will now start with a default configuration."
39 
40 
41 #include <tilda-config.h>
42 
43 #include "debug.h"
44 #include "tilda.h"
45 #include "configsys.h"
46 #include "tilda_window.h"
47 #include "key_grabber.h" /* for pull */
48 #include "wizard.h"
49 #include "xerror.h"
50 #include "tomboykeybinder.h"
51 #include "tilda-keybinding.h"
52 #include "tilda-cli-options.h"
53 
54 #include <sys/ioctl.h>
55 #include <sys/stat.h>
56 #include <sys/file.h>
57 #include <errno.h>
58 #include <dirent.h>
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <string.h>
62 #include <unistd.h>
63 #include <stdlib.h>
64 #include <gtk/gtk.h>
65 #include <glib-object.h>
66 #include <glib.h>
67 #include <glib/gi18n.h>
68 #include <locale.h>
69 #include <stdio.h>
70 #include <signal.h>
71 #include <pwd.h>
72 
73 #include <X11/Xlib.h>
74 #include <X11/Xlibint.h>
75 
76 #include <vte/vte.h>
77 #include <glib/gstdio.h>
78 
79 /**
80 * If lock->pid is 0 then the file is not opened exclusively. Instead flock() must be used to obtain a lock.
81 * Otherwise an exclusive lock file is created for the process.
82 */
create_lock_file(struct lock_info * lock)83 static gchar *create_lock_file (struct lock_info *lock)
84 {
85     DEBUG_FUNCTION ("create_lock_file");
86     DEBUG_ASSERT (lock != NULL);
87     DEBUG_ASSERT (lock->instance >= 0);
88     DEBUG_ASSERT (lock->pid >= 0);
89 
90     gint ret;
91     gchar *lock_file_full;
92     gchar *lock_dir = g_build_filename (g_get_user_cache_dir (), "tilda", "locks", NULL);
93     gchar *lock_file = g_strdup_printf ("lock_%d_%d", lock->pid, lock->instance);
94 
95     /* Make the ~/.cache/tilda/locks directory */
96     ret = g_mkdir_with_parents (lock_dir,  S_IRUSR | S_IWUSR | S_IXUSR);
97 
98     if (ret == -1)
99         goto mkdir_fail;
100 
101     /* Create the full path to the lock file */
102     lock_file_full = g_build_filename (lock_dir, lock_file, NULL);
103 
104     /* Create the lock file */
105     if(lock->pid == 0) {
106         ret = g_open(lock_file_full, O_CREAT, S_IRUSR | S_IWUSR);
107     } else {
108         ret = g_open(lock_file_full, O_WRONLY | O_CREAT | O_EXCL, 0);
109     }
110 
111     if (ret == -1)
112         goto creat_fail;
113 
114     lock->file_descriptor = ret;
115 
116     g_free (lock_file);
117     g_free (lock_dir);
118 
119     return lock_file_full;
120 
121     /* Free memory and return NULL */
122 creat_fail:
123     g_free (lock_file_full);
124 mkdir_fail:
125     g_free (lock_file);
126     g_free (lock_dir);
127 
128     return NULL;
129 }
130 
131 /**
132  * Check if a filename corresponds to a valid lockfile. Note that this
133  * routine does NOT check whether it is a stale lock, however. This
134  * will return the lock file's corresponding pid, if it is a valid lock.
135  *
136  * @param filename the filename to check
137  * @return a new struct lock_info
138  *
139  * Success: struct lock_info will be filled in and non-NULL
140  * Failure: return NULL
141  */
islockfile(const gchar * filename)142 static struct lock_info *islockfile (const gchar *filename)
143 {
144     DEBUG_FUNCTION ("islockfile");
145     DEBUG_ASSERT (filename != NULL);
146 
147     struct lock_info *lock;
148 
149     lock = g_malloc (sizeof (struct lock_info));
150 
151     if (lock == NULL)
152         return NULL;
153 
154 #ifdef USE_GLIB_2_14
155     GRegex *regex;
156     GMatchInfo *match_info;
157     gboolean matched;
158     gchar *temp;
159 
160     regex = g_regex_new ("^lock_(\d+)_(\d+)$", 0, 0, NULL);
161     matched = g_regex_match (regex, filename, 0, &match_info);
162 
163     if (!matched)
164     {
165         g_free (lock);
166         lock = NULL;
167         goto nomatch;
168     }
169 
170     /* Get the lock pid */
171     temp = g_match_info_fetch (match_info, 0);
172     lock->pid = atoi (temp);
173     g_free (temp);
174 
175     /* Get the configuration number */
176     temp = g_match_info_fetch (match_info, 1);
177     lock->instance = atoi (temp);
178     g_free (temp);
179 
180 nomatch:
181     if (match_info)
182         g_match_info_free (match_info);
183 
184     g_regex_unref (regex);
185 
186     return matched;
187 
188 #else /* Glib version is <2.14 */
189 
190     gboolean matches = g_str_has_prefix (filename, "lock_");
191     gboolean islock = FALSE;
192     gchar *pid_s, *instance_s;
193 
194     if (matches) /* we are prefixed with "lock_" and are probably a lock */
195     {
196         pid_s = strstr (filename, "_");
197 
198         if (pid_s) /* we have a valid pid */
199         {
200             /* Advance the pointer past the underscore */
201             pid_s++;
202 
203             lock->pid = atoi (pid_s);
204             instance_s = strstr (pid_s, "_");
205 
206             if (lock->pid > 0 && instance_s)
207             {
208                 /* Advance the pointer past the underscore */
209                 instance_s++;
210 
211                 /* Extract the instance number and store it */
212                 lock->instance = atoi (instance_s);
213 
214                 /* we parsed everything, so yes, we were a lock */
215                 islock = TRUE;
216             }
217         }
218     }
219 
220     if (!islock)
221     {
222         g_free (lock);
223         lock = NULL;
224     }
225 
226     return lock;
227 #endif
228 }
229 
230 /**
231 * Gets a list of the pids in
232 */
getPids()233 static GSList *getPids() {
234     GSList *pids = NULL;
235     FILE *ps_output;
236     const gchar ps_command[] = "pgrep tilda";
237     gchar buf[16]; /* Really shouldn't need more than 6 */
238 
239     if ((ps_output = popen (ps_command, "r")) == NULL) {
240         g_printerr (_("Unable to run command: `%s'\n"), ps_command);
241         return NULL;
242     }
243 
244     /* The popen() succeeded, get all of the pids */
245     while (fgets (buf, sizeof(buf), ps_output) != NULL)
246         pids = g_slist_append (pids, GINT_TO_POINTER (atoi (buf)));
247 
248     /* We've read all of the pids, exit */
249     pclose (ps_output);
250     return pids;
251 }
252 
253 /**
254  * Remove stale lock files from the ~/.tilda/locks/ directory.
255  *
256  * Success: returns 0
257  * Failure: returns non-zero
258  */
remove_stale_lock_files()259 static gint remove_stale_lock_files ()
260 {
261     DEBUG_FUNCTION ("remove_stale_lock_files");
262 
263     GSList *pids = getPids();
264     if(pids == NULL) {
265         return -1;
266     }
267 
268     struct lock_info *lock;
269     gchar *lock_dir = g_build_filename (g_get_user_cache_dir (), "tilda", "locks", NULL);
270     gchar *remove_file;
271     gchar *filename;
272     GDir *dir;
273 
274     /* if the lock dir does not exist then there are no stale lock files to remove. */
275     if (!g_file_test (lock_dir, G_FILE_TEST_EXISTS)) {
276         g_free (lock_dir);
277         return 0;
278     }
279 
280     /* Open the lock directory for reading */
281     dir = g_dir_open (lock_dir, 0, NULL);
282 
283     if (dir == NULL)
284     {
285         g_printerr (_("Unable to open lock directory: %s\n"), lock_dir);
286         g_free (lock_dir);
287         return -2;
288     }
289 
290     /* For each possible lock file, check if it is a lock, and see if
291      * it matches one of the running tildas */
292     while ((filename = (gchar*) g_dir_read_name (dir)) != NULL)
293     {
294         lock = islockfile (filename);
295 
296         if (lock && (g_slist_find (pids, GINT_TO_POINTER (lock->pid)) == NULL))
297         {
298             /* We have found a stale element */
299             remove_file = g_build_filename (lock_dir, filename, NULL);
300             g_remove (remove_file);
301             g_free (remove_file);
302         }
303 
304         if (lock)
305             g_free (lock);
306     }
307 
308     g_dir_close (dir);
309     g_free (lock_dir);
310     g_slist_free(pids);
311 
312     return 0;
313 }
314 
315 /**
316  * Set values in the config from command-line parameters
317  *
318  * @param cli_options pointer to a struct containing command-line options
319  */
setup_config_from_cli_options(tilda_cli_options * cli_options)320 static void setup_config_from_cli_options(tilda_cli_options *cli_options)
321 {
322     if (cli_options->background_color != NULL
323             && cli_options->background_color != config_getstr ("background_color")) {
324         config_setstr ("background_color", cli_options->background_color);
325 
326         GdkRGBA col;
327         if (gdk_rgba_parse (&col, cli_options->background_color))
328         {
329             config_setint("back_red", GUINT16_FROM_FLOAT (col.red));
330             config_setint("back_green", GUINT16_FROM_FLOAT (col.green));
331             config_setint("back_blue", GUINT16_FROM_FLOAT (col.blue));
332         }
333 
334         g_free(cli_options->background_color);
335     }
336     if (cli_options->command != NULL
337             && cli_options->command != config_getstr ("command"))
338     {
339         config_setbool ("run_command", TRUE);
340         config_setstr ("command", cli_options->command);
341         g_free(cli_options->command);
342     }
343     if (cli_options->font != NULL
344             && cli_options->font != config_getstr ("font")) {
345         config_setstr ("font", cli_options->font);
346         g_free(cli_options->font);
347     }
348 
349     if (cli_options->back_alpha != 0
350             && cli_options->back_alpha != config_getint ("back_alpha"))
351     {
352         config_setbool ("enable_transparency", ~cli_options->back_alpha & 0xffff);
353         config_setint ("back_alpha", cli_options->back_alpha);
354     }
355 
356     if (cli_options->working_dir != NULL
357             && cli_options->working_dir != config_getstr ("working_dir")) {
358         config_setstr ("working_dir", cli_options->working_dir);
359         g_free(cli_options->working_dir);
360     }
361 
362     if (cli_options->lines != 0
363             && cli_options->lines != config_getint ("lines"))
364         config_setint ("lines", cli_options->lines);
365     if (cli_options->x_pos != 0
366             && cli_options->x_pos != config_getint ("x_pos"))
367         config_setint ("x_pos", cli_options->x_pos);
368     if (cli_options->y_pos != 0
369             && cli_options->y_pos != config_getint ("y_pos"))
370         config_setint ("y_pos", cli_options->y_pos);
371 
372     if (cli_options->hidden != FALSE
373             && cli_options->hidden != config_getbool ("hidden"))
374         config_setbool ("hidden", cli_options->hidden);
375     if (cli_options->scrollbar != FALSE
376             && cli_options->scrollbar != config_getbool ("scrollbar"))
377         config_setbool ("scrollbar", cli_options->scrollbar);
378 }
379 
380 /**
381  * Get a pointer to the config file name for this instance.
382  *
383  * NOTE: you MUST call free() on the returned value!!!
384  *
385  * @param tw the tilda_window structure corresponding to this instance
386  * @return a pointer to a string representation of the config file's name
387  */
get_config_file_name(gint instance)388 static gchar *get_config_file_name (gint instance)
389 {
390     DEBUG_FUNCTION ("get_config_file_name");
391     DEBUG_ASSERT (instance >= 0);
392 
393     gchar *config_dir = g_build_filename (g_get_user_config_dir (), "tilda", NULL);
394 
395     /* Make the ~/.config/tilda directory */
396     if (!g_file_test (config_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
397         g_print (_("Creating directory:'%s'\n"), config_dir);
398         g_mkdir_with_parents (config_dir,  S_IRUSR | S_IWUSR | S_IXUSR);
399     }
400 
401     gchar *config_file_prefix = g_build_filename (config_dir, "config_", NULL);
402     gchar *config_file;
403 
404     config_file = g_strdup_printf ("%s%d", config_file_prefix, instance);
405     g_free (config_file_prefix);
406 
407     /* resolve possible symlink pointing to a different location. */
408     gchar * resolved_config_file = realpath (config_file, NULL);
409 
410     if (g_strcmp0 (config_file, resolved_config_file) != 0) {
411         g_debug ("Config file at '%s' points to '%s'", config_file, resolved_config_file);
412     }
413 
414     if (resolved_config_file != NULL) {
415         g_free (config_file);
416         /* resolved_config_file must be freed with free(3) so we duplicate the
417          * string to ensure that what ever we return from this function can be
418          * freed with g_free(). */
419         config_file = g_strdup (resolved_config_file);
420         free (resolved_config_file);
421     }
422 
423     return config_file;
424 }
425 
_cmp_locks(gconstpointer a,gconstpointer b,gpointer userdata)426 static gint _cmp_locks(gconstpointer a, gconstpointer b, gpointer userdata) {
427   return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b);
428 }
429 
430 /**
431  * get_instance_number ()
432  *
433  * Gets the next available tilda instance number. This will always pick the
434  * lowest non-running tilda available.
435  *
436  * Success: return next available instance number (>=0)
437  * Failure: return 0
438  */
get_instance_number()439 static gint get_instance_number ()
440 {
441     DEBUG_FUNCTION ("get_instance_number");
442 
443     gchar *name;
444 
445     GSequence *seq;
446     GSequenceIter *iter;
447     gint lowest_lock_instance = 0;
448     gint current_lock_instance;
449 
450     GDir *dir;
451     struct lock_info *lock;
452     gchar *lock_dir = g_build_filename (g_get_user_cache_dir (), "tilda", "locks", NULL);
453 
454     /* Open the lock directory */
455     dir = g_dir_open (lock_dir, 0, NULL);
456 
457     /* Check for failure to open */
458     if (dir == NULL)
459     {
460         g_printerr (_("Unable to open lock directory: %s\n"), lock_dir);
461         g_free (lock_dir);
462         return 0;
463     }
464 
465     /* Look through every file in the lock directory, and see if it is a lock file.
466      * If it is a lock file, insert it in a sorted sequence. */
467     seq = g_sequence_new(NULL);
468     while ((name = (gchar*)g_dir_read_name (dir)) != NULL)
469     {
470         lock = islockfile (name);
471 
472         if (lock != NULL)
473         {
474             g_sequence_insert_sorted(seq, GINT_TO_POINTER(lock->instance), _cmp_locks, NULL);
475             g_free (lock);
476         }
477     }
478 
479     g_dir_close (dir);
480     g_free (lock_dir);
481 
482     /* We iterate the sorted sequence of lock instances to find the first (lowest) number *not* taken. */
483     for (iter = g_sequence_get_begin_iter(seq); !g_sequence_iter_is_end(iter); iter = g_sequence_iter_next(iter)) {
484       current_lock_instance = GPOINTER_TO_INT(g_sequence_get(iter));
485       if (lowest_lock_instance < current_lock_instance)
486         break;
487       else
488         lowest_lock_instance = current_lock_instance + 1;
489     }
490 
491     g_sequence_free(seq);
492 
493     return lowest_lock_instance;
494 }
495 
termination_handler(G_GNUC_UNUSED gint signum)496 static void termination_handler (G_GNUC_UNUSED gint signum) {
497     DEBUG_FUNCTION ("termination_handler");
498     gtk_main_quit ();
499 }
500 
501 /*
502  * This is to do the migration of config files from ~/.tilda to the
503  * XDG_*_HOME folders
504  */
migrate_config_files(char * old_config_path)505 static void migrate_config_files(char *old_config_path) {
506     gchar* old_lock_dir = g_build_filename(old_config_path, "locks", NULL);
507     gchar* new_lock_dir = g_build_filename(g_get_user_cache_dir (), "tilda", "locks", NULL);
508     gchar* new_config_dir = g_build_filename(g_get_user_config_dir (), "tilda", NULL);
509 
510     if(!g_file_test(new_lock_dir, G_FILE_TEST_IS_DIR)) {
511            g_mkdir_with_parents(new_lock_dir, 0700);
512     }
513 
514     //we basically need to move the files from old_config_path to config and cache
515     g_rename(old_lock_dir, new_lock_dir);
516     //we must move the config files after we have moved the locks directory, otherwise it gets moved aswell
517     g_rename(old_config_path, new_config_dir);
518     g_free(old_lock_dir);
519     g_free(new_lock_dir);
520     g_free(new_config_dir);
521 }
522 
load_application_css()523 static void load_application_css () {
524     GtkCssProvider *provider;
525     const gchar* style;
526     GError *error;
527 
528     provider = gtk_css_provider_new ();
529 
530     gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
531                                                GTK_STYLE_PROVIDER (provider),
532                                                GTK_STYLE_PROVIDER_PRIORITY_USER);
533 
534     style = "#search{background:#fff;}";
535     error = NULL;
536     gtk_css_provider_load_from_data (provider, style, -1, &error);
537 
538     if (error) {
539         g_print ("Error %s\n", error->message);
540         g_error_free (error);
541     }
542 }
543 
load_custom_css_file()544 static void load_custom_css_file () {
545     GtkCssProvider *provider;
546     GFile *file;
547     GError *error;
548     gchar *filename;
549 
550     filename = g_build_filename (g_get_user_config_dir (),
551                                  "tilda", "style.css", NULL);
552 
553     if (!g_file_test (filename, G_FILE_TEST_EXISTS))
554         return;
555 
556     g_print (_("Found style.css in the user config directory, "
557                "applying user css style.\n"));
558 
559     provider = gtk_css_provider_new ();
560 
561     gtk_style_context_add_provider_for_screen (gdk_screen_get_default(),
562                                                GTK_STYLE_PROVIDER(provider),
563                                                GTK_STYLE_PROVIDER_PRIORITY_USER);
564 
565 
566     file = g_file_new_for_path (filename);
567     error = NULL;
568     gtk_css_provider_load_from_file (provider, file, &error);
569 
570     if (error) {
571         g_print ("Error: %s", error->message);
572         g_error_free (error);
573     }
574 
575     g_object_unref (file);
576     g_free (filename);
577 }
578 
main(int argc,char * argv[])579 int main (int argc, char *argv[])
580 {
581 #ifdef DEBUG
582     /**
583      * This enables the tilda log domain while we are in debug mode. This
584      * is for convenience such that we do not need to start tilda with
585      * 'G_MESSAGES_DEBUG=tilda ./tilda' each time we start tilda.
586      */
587 
588     g_setenv ("G_MESSAGES_DEBUG", "tilda", FALSE);
589 #endif
590 
591     DEBUG_FUNCTION_MESSAGE ("main", "Using libvte version: %i.%i.%i",
592                             VTE_MAJOR_VERSION, VTE_MINOR_VERSION, VTE_MICRO_VERSION);
593 
594     /* Set supported backend to X11 */
595     gdk_set_allowed_backends ("x11");
596 
597     tilda_window tw;
598     /* NULL set the tw pointers so we can get a clean exit on initialization failure */
599     memset(&tw, 0, sizeof(tilda_window));
600 
601     struct sigaction sa;
602     struct lock_info lock;
603     gboolean need_wizard = FALSE;
604     gchar *config_file, *lock_file, *old_config_path;
605 
606     /*
607      * Migration code to move old files to new XDG folders
608      */
609     old_config_path = g_build_filename(g_get_home_dir (), ".tilda", NULL);
610     if (g_file_test(old_config_path, G_FILE_TEST_IS_DIR)) {
611         g_print (_("Migrating old config path to XDG folders\n"));
612         migrate_config_files(old_config_path);
613         g_free(old_config_path);
614     }
615 
616     /* Remove stale lock files */
617     remove_stale_lock_files ();
618 
619     /* The global lock file is used to synchronize the start up of multiple simultaneously starting tilda processes.
620      * The processes will synchronize on a lock file named lock_0_0, such that the part of determining the instance
621      * number and creating the per process lock file (lock_<pid>_<instance>) is atomic. Without this it could
622      * happen, that a second tilda instance was trying to determine its instance number before the first instance
623      * had finished creating its lock file, this resulted in two processes with the same instance number and could lead
624      * to corruption of the config file.
625      * In order to test if this works the following shell command can be used: "tilda & tilda && fg", which causes
626      * two tilda processes to be started simultaneously. See:
627      *
628      *     http://stackoverflow.com/questions/3004811/how-do-you-run-multiple-programs-from-a-bash-script
629      */
630     struct lock_info global_lock;
631     global_lock.instance = 0;
632     global_lock.pid = 0;
633     gchar *global_lock_file = NULL;
634 
635     global_lock_file = create_lock_file(&global_lock);
636     if(global_lock_file == NULL) {
637         perror("Error creating global lock file");
638         return EXIT_FAILURE;
639     }
640     flock(global_lock.file_descriptor, LOCK_EX);
641 
642     /* Start of atomic section. */
643     lock.pid = getpid ();
644     lock.instance = get_instance_number ();
645     lock_file = create_lock_file (&lock);
646 
647     /* End of atomic section */
648 
649     flock(global_lock.file_descriptor, LOCK_UN);
650     g_remove (global_lock_file);
651     close(lock.file_descriptor);
652     g_free(global_lock_file);
653 
654 
655 #if ENABLE_NLS
656     /* Gettext Initialization */
657     char* locale = setlocale (LC_ALL, "");
658     if(!locale) {
659         g_warning ("Could not setup locale.");
660     }
661     bindtextdomain (PACKAGE, LOCALEDIR);
662     bind_textdomain_codeset (PACKAGE, "UTF-8");
663     textdomain (PACKAGE);
664 #endif
665 
666     config_file = NULL;
667 
668     /* Parse the command line */
669     tilda_cli_options *cli_options = tilda_cli_options_new ();
670     need_wizard = tilda_cli_options_parse_options (cli_options, argc, argv, &config_file);
671 
672     if (config_file) {	  // if there was a config file specified via cli
673         if (!g_file_test (config_file, G_FILE_TEST_EXISTS)) {
674             g_printerr (_("Specified config file '%s' does not exist. Reverting to default path.\n"),
675                     config_file);
676             config_file = get_config_file_name (lock.instance);
677         }
678     } else {    // if not, we look for the defaut config file
679         config_file = get_config_file_name (lock.instance);
680     }
681 
682     /* Initialize GTK. Any code that interacts with GTK (e.g. creating a widget)
683      * should come after this call. Gtk initialization should happen before we
684      * initialize the config file. */
685     gtk_init (&argc, &argv);
686 
687     /* Start up the configuration system and load from file */
688     gint config_init_result = config_init (config_file);
689 
690     /* Set up possible overridden config options */
691     setup_config_from_cli_options(cli_options);
692     g_free(cli_options);
693 
694     /* We're about to startup X, so set the error handler. */
695     XSetErrorHandler (xerror_handler);
696 
697     /* This section shows a modal dialog to notify the user that something has gone wrong when loading the config.
698      * Earlier version only used to print a message to stderr, but since tilda is usually not started from a
699      * console this message would have been lost and a message dialog is much more user friedly.
700      */
701     GtkWidget *dialog = NULL;
702     if(config_init_result == 1) {
703         dialog = gtk_message_dialog_new_with_markup(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
704                                         TILDA_CONFIG_PARSE_ERROR);
705     } else if (config_init_result != 0) {
706         dialog = gtk_message_dialog_new_with_markup(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
707                                         TILDA_CONFIG_OTHER_ERROR);
708     }
709 
710     if(dialog) {
711         g_message("Running Dialog");
712         gtk_dialog_run(GTK_DIALOG(dialog));
713         gtk_widget_destroy(dialog);
714     }
715 
716     load_application_css ();
717     load_custom_css_file ();
718 
719     /* create new tilda_window */
720     gboolean success = tilda_window_init (config_file, lock.instance, &tw);
721 
722     if(!success) {
723         fprintf(stderr, "tilda.c: initialization failed\n");
724         goto initialization_failed;
725     }
726 
727     /* Adding widget title for CSS selection */
728     gtk_widget_set_name (GTK_WIDGET(tw.window), "Main");
729 
730     /* Initialize and set up the keybinding to toggle tilda's visibility. */
731     tomboy_keybinder_init ();
732 
733     /* Hook up signal handlers */
734     sa.sa_handler = termination_handler;
735     sigemptyset (&sa.sa_mask);
736     sa.sa_flags = 0;
737 
738     sigaction (SIGINT,  &sa, NULL);
739     sigaction (SIGQUIT, &sa, NULL);
740     sigaction (SIGABRT, &sa, NULL);
741     sigaction (SIGTERM, &sa, NULL);
742     sigaction (SIGKILL, &sa, NULL);
743 
744     /* If the config file doesn't exist open up the wizard */
745     if (access (tw.config_file, R_OK) == -1)
746     {
747         /* We probably need a default key, too ... */
748         gchar *default_key = g_strdup_printf ("F%d", tw.instance+1);
749         config_setstr ("key", default_key);
750         g_free (default_key);
751 
752         need_wizard = TRUE;
753     }
754 
755     /* Show the wizard if we need to.
756      *
757      * Note that the key will be bound upon exiting the wizard */
758     if (need_wizard) {
759         g_print ("Starting the wizard to configure tilda options.\n");
760         wizard (&tw);
761     } else {
762         gint ret = tilda_keygrabber_bind (config_getstr ("key"), &tw);
763 
764         if (!ret)
765         {
766             /* The key was unbindable, so we need to show the wizard */
767             const char *message = _("The keybinding you chose for \"Pull Down Terminal\" is invalid. Please choose another.");
768 
769             tilda_keybinding_show_invalid_keybinding_dialog (NULL,
770                                                              message);
771             wizard (&tw);
772         }
773     }
774 
775     pull (&tw, config_getbool ("hidden") ? PULL_UP : PULL_DOWN, FALSE);
776 
777     g_print ("Tilda has started. Press %s to pull down the window.\n",
778         config_getstr ("key"));
779     /* Whew! We're finally all set up and ready to run GTK ... */
780     gtk_main();
781 
782 initialization_failed:
783     tilda_window_free(&tw);
784 
785     /* Ok, we're at the end of our run. Time to clean up ... */
786     config_free (config_file);
787     g_remove (lock_file);
788     close(lock.file_descriptor);
789     g_free (lock_file);
790     g_free (config_file);
791     return 0;
792 }
793