Bug Summary

File:core/main.c
Warning:line 429, column 18
Using a fixed address is not portable because that address will probably not be valid in all environments or platforms

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -D HAVE_CONFIG_H -I . -I .. -I ./include -D CROMA_LIBEXECDIR="/usr/local/libexec" -D HOST_ALIAS="" -D CROMA_LOCALEDIR="/usr/local/share/locale" -D CROMA_PKGDATADIR="/usr/local/share/croma" -D CROMA_DATADIR="/usr/local/share" -D G_LOG_DOMAIN="croma" -D SN_API_NOT_YET_FROZEN=1 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/uuid -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D _REENTRANT -D _REENTRANT -I /usr/include/startup-notification-1.0 -I /usr/include/libgtop-2.0 -D PIC -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-12-31-024951-30308-1 -x c core/main.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3/* Croma main() */
4
5/*
6 * Copyright (C) 2001 Havoc Pennington
7 * Copyright (C) 2006 Elijah Newren
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24
25/**
26 * \file
27 * Program startup.
28 * Functions which parse the command-line arguments, create the display,
29 * kick everything off and then close down Croma when it's time to go.
30 */
31
32/**
33 * \mainpage
34 * Croma - a boring window manager for the adult in you
35 *
36 * Many window managers are like Marshmallow Froot Loops; Croma
37 * is like Cheerios.
38 *
39 * The best way to get a handle on how the whole system fits together
40 * is discussed in doc/code-overview.txt; if you're looking for functions
41 * to investigate, read main(), meta_display_open(), and event_callback().
42 */
43
44#define _GNU_SOURCE
45#define _XOPEN_SOURCE700 /* for putenv() and some signal-related functions */
46
47#include <config.h>
48#include "main.h"
49#include "util.h"
50#include "display-private.h"
51#include "errors.h"
52#include "ui.h"
53#include "session.h"
54#include "prefs.h"
55#include "core.h"
56
57#include <glib-object.h>
58#include <glib/gprintf.h>
59
60#include <stdlib.h>
61#include <sys/types.h>
62#include <sys/wait.h>
63#include <stdio.h>
64#include <string.h>
65#include <signal.h>
66#include <unistd.h>
67#include <errno(*__errno_location ()).h>
68#include <fcntl.h>
69#include <locale.h>
70#include <time.h>
71#include <unistd.h>
72
73/**
74 * The exit code we'll return to our parent process when we eventually die.
75 */
76static MetaExitCode meta_exit_code = META_EXIT_SUCCESS;
77
78/**
79 * Handle on the main loop, so that we have an easy way of shutting Croma
80 * down.
81 */
82static GMainLoop *meta_main_loop = NULL((void*)0);
83
84/**
85 * If set, Croma will spawn an identical copy of itself immediately
86 * before quitting.
87 */
88static gboolean meta_restart_after_quit = FALSE(0);
89
90static void prefs_changed_callback (MetaPreference pref,
91 gpointer data);
92
93/**
94 * Prints log messages. If Croma was compiled with backtrace support,
95 * also prints a backtrace (see meta_print_backtrace()).
96 *
97 * \param log_domain the domain the error occurred in (we ignore this)
98 * \param log_level the log level so that we can filter out less
99 * important messages
100 * \param message the message to log
101 * \param user_data arbitrary data (we ignore this)
102 */
103static void
104log_handler (const gchar *log_domain,
105 GLogLevelFlags log_level,
106 const gchar *message,
107 gpointer user_data)
108{
109 meta_warning ("Log level %d: %s\n", log_level, message);
110 meta_print_backtrace ();
111}
112
113/**
114 * Prints the version notice. This is shown when Croma is called
115 * with the --version switch.
116 */
117static void
118version (void)
119{
120 const int latest_year = 2009;
121 char yearbuffer[256];
122 GDate date;
123
124 /* this is all so the string to translate stays constant.
125 * see how much we love the translators.
126 */
127 g_date_set_dmy (&date, 1, G_DATE_JANUARY, latest_year);
128 if (g_date_strftime (yearbuffer, sizeof (yearbuffer), "%Y", &date)==0)
129 /* didn't work? fall back to decimal representation */
130 g_sprintf (yearbuffer, "%d", latest_year);
131
132 g_print (_("croma %s\n"dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
)
133 "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n"dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
)
134 "This is free software; see the source for copying conditions.\n"dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
)
135 "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
)
,
136 VERSION"1.25.1", yearbuffer);
137 exit (0);
138}
139
140/**
141 * Prints a list of which configure script options were used to
142 * build this copy of Croma. This is actually always called
143 * on startup, but it's all no-op unless we're in verbose mode
144 * (see meta_set_verbose).
145 */
146static void
147meta_print_compilation_info (void)
148{
149#ifdef HAVE_SHAPE
150 meta_verbosemeta_verbose_real ("Compiled with shape extension\n");
151#else
152 meta_verbosemeta_verbose_real ("Compiled without shape extension\n");
153#endif
154#ifdef HAVE_XINERAMA
155 meta_topicmeta_topic_real (META_DEBUG_XINERAMA, "Compiled with Xinerama extension\n");
156#else
157 meta_topicmeta_topic_real (META_DEBUG_XINERAMA, "Compiled without Xinerama extension\n");
158#endif
159#ifdef HAVE_XFREE_XINERAMA
160 meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (using XFree86 Xinerama)\n");
161#else
162 meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (not using XFree86 Xinerama)\n");
163#endif
164#ifdef HAVE_SOLARIS_XINERAMA
165 meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (using Solaris Xinerama)\n");
166#else
167 meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (not using Solaris Xinerama)\n");
168#endif
169#ifdef HAVE_XSYNC
170 meta_verbosemeta_verbose_real ("Compiled with sync extension\n");
171#else
172 meta_verbosemeta_verbose_real ("Compiled without sync extension\n");
173#endif
174#ifdef HAVE_RANDR
175 meta_verbosemeta_verbose_real ("Compiled with randr extension\n");
176#else
177 meta_verbosemeta_verbose_real ("Compiled without randr extension\n");
178#endif
179#ifdef HAVE_STARTUP_NOTIFICATION
180 meta_verbosemeta_verbose_real ("Compiled with startup notification\n");
181#else
182 meta_verbosemeta_verbose_real ("Compiled without startup notification\n");
183#endif
184#ifdef HAVE_COMPOSITE_EXTENSIONS1
185 meta_verbosemeta_verbose_real ("Compiled with composite extensions\n");
186#else
187 meta_verbosemeta_verbose_real ("Compiled without composite extensions\n");
188#endif
189}
190
191/**
192 * Prints the version number, the current timestamp (not the
193 * build date), the locale, the character encoding, and a list
194 * of configure script options that were used to build this
195 * copy of Croma. This is actually always called
196 * on startup, but it's all no-op unless we're in verbose mode
197 * (see meta_set_verbose).
198 */
199static void
200meta_print_self_identity (void)
201{
202 char buf[256];
203 GDate d;
204 const char *charset;
205
206 /* Version and current date. */
207 g_date_clear (&d, 1);
208 g_date_set_time_t (&d, time (NULL((void*)0)));
209 g_date_strftime (buf, sizeof (buf), "%x", &d);
210 meta_verbosemeta_verbose_real ("Croma version %s running on %s\n",
211 VERSION"1.25.1", buf);
212
213 /* Locale and encoding. */
214 g_get_charset (&charset);
215 meta_verbosemeta_verbose_real ("Running in locale \"%s\" with encoding \"%s\"\n",
216 setlocale (LC_ALL6, NULL((void*)0)), charset);
217
218 /* Compilation settings. */
219 meta_print_compilation_info ();
220}
221
222/**
223 * The set of possible options that can be set on Croma's
224 * command line. This type exists so that meta_parse_options() can
225 * write to an instance of it.
226 */
227typedef struct
228{
229 gchar *save_file;
230 gchar *display_name;
231 gchar *client_id;
232 gboolean replace_wm;
233 gboolean disable_sm;
234 gboolean print_version;
235 gboolean sync;
236 gboolean composite;
237 gboolean no_composite;
238 gboolean no_force_fullscreen;
239} MetaArguments;
240
241#ifdef HAVE_COMPOSITE_EXTENSIONS1
242#define COMPOSITE_OPTS_FLAGS0 0
243#else /* HAVE_COMPOSITE_EXTENSIONS */
244/* No compositor, so don't show the arguments in --help */
245#define COMPOSITE_OPTS_FLAGS0 G_OPTION_FLAG_HIDDEN
246#endif /* HAVE_COMPOSITE_EXTENSIONS */
247
248/**
249 * Parses argc and argv and returns the
250 * arguments that Croma understands in meta_args.
251 *
252 * The strange call signature has to be written like it is so
253 * that g_option_context_parse() gets a chance to modify argc and
254 * argv.
255 *
256 * \param argc Pointer to the number of arguments Croma was given
257 * \param argv Pointer to the array of arguments Croma was given
258 * \param meta_args The result of parsing the arguments.
259 **/
260static void
261meta_parse_options (int *argc, char ***argv,
262 MetaArguments *meta_args)
263{
264 MetaArguments my_args = { .replace_wm = FALSE(0),
265 .disable_sm = FALSE(0),
266 .print_version = FALSE(0),
267 .sync = FALSE(0),
268 .composite = FALSE(0) };
269
270 GOptionEntry options[] = {
271 {
272 "sm-disable", 0, 0, G_OPTION_ARG_NONE,
273 &my_args.disable_sm,
274 N_("Disable connection to session manager")"Disable connection to session manager",
275 NULL((void*)0)
276 },
277 {
278 "replace", 0, 0, G_OPTION_ARG_NONE,
279 &my_args.replace_wm,
280 N_("Replace the running window manager with Croma")"Replace the running window manager with Croma",
281 NULL((void*)0)
282 },
283 {
284 "sm-client-id", 0, 0, G_OPTION_ARG_STRING,
285 &my_args.client_id,
286 N_("Specify session management ID")"Specify session management ID",
287 "ID"
288 },
289 {
290 "display", 'd', 0, G_OPTION_ARG_STRING,
291 &my_args.display_name, N_("X Display to use")"X Display to use",
292 "DISPLAY"
293 },
294 {
295 "sm-save-file", 0, 0, G_OPTION_ARG_FILENAME,
296 &my_args.save_file,
297 N_("Initialize session from savefile")"Initialize session from savefile",
298 "FILE"
299 },
300 {
301 "version", 0, 0, G_OPTION_ARG_NONE,
302 &my_args.print_version,
303 N_("Print version")"Print version",
304 NULL((void*)0)
305 },
306 {
307 "sync", 0, 0, G_OPTION_ARG_NONE,
308 &my_args.sync,
309 N_("Make X calls synchronous")"Make X calls synchronous",
310 NULL((void*)0)
311 },
312 {
313 "composite", 'c', COMPOSITE_OPTS_FLAGS0, G_OPTION_ARG_NONE,
314 &my_args.composite,
315 N_("Turn compositing on")"Turn compositing on",
316 NULL((void*)0)
317 },
318 {
319 "no-composite", 0, COMPOSITE_OPTS_FLAGS0, G_OPTION_ARG_NONE,
320 &my_args.no_composite,
321 N_("Turn compositing off")"Turn compositing off",
322 NULL((void*)0)
323 },
324 {
325 "no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS0, G_OPTION_ARG_NONE,
326 &my_args.no_force_fullscreen,
327 N_("Don't make fullscreen windows that are maximized and have no decorations")"Don't make fullscreen windows that are maximized and have no decorations",
328 NULL((void*)0)
329 },
330 {NULL((void*)0)}
331 };
332 GOptionContext *ctx;
333 GError *error = NULL((void*)0);
334
335 ctx = g_option_context_new (NULL((void*)0));
336 g_option_context_add_main_entries (ctx, options, "croma");
337 if (!g_option_context_parse (ctx, argc, argv, &error))
338 {
339 g_print ("croma: %s\n", error->message);
340 exit(1);
341 }
342 g_option_context_free (ctx);
343 /* Return the parsed options through the meta_args param. */
344 *meta_args = my_args;
345}
346
347/**
348 * Selects which display Croma should use. It first tries to use
349 * display_name as the display. If display_name is NULL then
350 * try to use the environment variable CROMA_DISPLAY. If that
351 * also is NULL, use the default - :0.0
352 */
353static void
354meta_select_display (gchar *display_name)
355{
356 gchar *envVar = "";
357 if (display_name)
358 envVar = g_strconcat ("DISPLAY=", display_name, NULL((void*)0));
359 else if (g_getenv ("CROMA_DISPLAY"))
360 envVar = g_strconcat ("DISPLAY=",
361 g_getenv ("CROMA_DISPLAY"), NULL((void*)0));
362 /* DO NOT FREE envVar, putenv() sucks */
363 putenv (envVar);
364}
365
366static void
367meta_finalize (void)
368{
369 MetaDisplay *display = meta_get_display();
370 if (display)
371 meta_display_close (display,
372 CurrentTime0L); /* I doubt correct timestamps matter here */
373
374 meta_session_shutdown ();
375}
376
377static int sigterm_pipe_fds[2] = { -1, -1 };
378
379static void
380sigterm_handler (int signum)
381{
382 if (sigterm_pipe_fds[1] >= 0)
383 {
384 G_GNUC_UNUSED__attribute__ ((__unused__)) int dummy;
385
386 dummy = write (sigterm_pipe_fds[1], "", 1);
387 close (sigterm_pipe_fds[1]);
388 sigterm_pipe_fds[1] = -1;
389 }
390}
391
392static gboolean
393on_sigterm (GIOChannel *source,
394 GIOCondition condition,
395 gpointer user_data)
396{
397 meta_quit (META_EXIT_SUCCESS);
398 return FALSE(0);
399}
400
401/**
402 * This is where the story begins. It parses commandline options and
403 * environment variables, sets up the screen, hands control off to
404 * CTK, and cleans up afterwards.
405 *
406 * \param argc Number of arguments (as usual)
407 * \param argv Array of arguments (as usual)
408 *
409 * \bug It's a bit long. It would be good to split it out into separate
410 * functions.
411 */
412int
413main (int argc, char **argv)
414{
415 struct sigaction act;
416 sigset_t empty_mask;
417 MetaArguments meta_args;
418 const gchar *log_domains[] = {
419 NULL((void*)0), G_LOG_DOMAIN"croma", "Ctk", "Cdk", "GLib",
420 "Pango", "GLib-GObject", "GThread"
421 };
422 guint i;
423 GIOChannel *channel;
424
425 if (setlocale (LC_ALL6, "") == NULL((void*)0))
1
Assuming the condition is false
2
Taking false branch
426 meta_warning ("Locale not understood by C library, internationalization will not work\n");
427
428 sigemptyset (&empty_mask);
429 act.sa_handler__sigaction_handler.sa_handler = SIG_IGN((__sighandler_t) 1);
3
Using a fixed address is not portable because that address will probably not be valid in all environments or platforms
430 act.sa_mask = empty_mask;
431 act.sa_flags = 0;
432 if (sigaction (SIGPIPE13, &act, NULL((void*)0)) < 0)
433 g_printerr ("Failed to register SIGPIPE handler: %s\n",
434 g_strerror (errno(*__errno_location ())));
435#ifdef SIGXFSZ25
436 if (sigaction (SIGXFSZ25, &act, NULL((void*)0)) < 0)
437 g_printerr ("Failed to register SIGXFSZ handler: %s\n",
438 g_strerror (errno(*__errno_location ())));
439#endif
440
441 if (pipe (sigterm_pipe_fds) != 0)
442 g_printerr ("Failed to create SIGTERM pipe: %s\n",
443 g_strerror (errno(*__errno_location ())));
444
445 channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
446 g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL((void*)0));
447 g_io_add_watch (channel, G_IO_IN, on_sigterm, NULL((void*)0));
448 g_io_channel_set_close_on_unref (channel, TRUE(!(0)));
449 g_io_channel_unref (channel);
450
451 act.sa_handler__sigaction_handler.sa_handler = &sigterm_handler;
452 if (sigaction (SIGTERM15, &act, NULL((void*)0)) < 0)
453 g_printerr ("Failed to register SIGTERM handler: %s\n",
454 g_strerror (errno(*__errno_location ())));
455
456 if (g_getenv ("CROMA_VERBOSE"))
457 meta_set_verbose (TRUE(!(0)));
458 if (g_getenv ("CROMA_DEBUG"))
459 meta_set_debugging (TRUE(!(0)));
460
461 if (g_get_home_dir ())
462 if (chdir (g_get_home_dir ()) < 0)
463 meta_warning ("Could not change to home directory %s.\n",
464 g_get_home_dir ());
465
466 meta_print_self_identity ();
467
468 bindtextdomain (GETTEXT_PACKAGE"croma", CROMA_LOCALEDIR"/usr/local/share/locale");
469 bind_textdomain_codeset (GETTEXT_PACKAGE"croma", "UTF-8");
470 textdomain (GETTEXT_PACKAGE"croma");
471
472 /* Parse command line arguments.*/
473 meta_parse_options (&argc, &argv, &meta_args);
474
475 meta_set_syncing (meta_args.sync || (g_getenv ("CROMA_SYNC") != NULL((void*)0)));
476
477 if (meta_args.print_version)
478 version ();
479
480 meta_select_display (meta_args.display_name);
481
482 if (meta_args.replace_wm)
483 meta_set_replace_current_wm (TRUE(!(0)));
484
485 if (meta_args.save_file && meta_args.client_id)
486 meta_fatal ("Can't specify both SM save file and SM client id\n");
487
488 meta_main_loop = g_main_loop_new (NULL((void*)0), FALSE(0));
489
490 meta_ui_init (&argc, &argv);
491
492 /* Load prefs */
493 meta_prefs_init ();
494 meta_prefs_add_listener (prefs_changed_callback, NULL((void*)0));
495
496
497#if 1
498
499 for (i=0; i<G_N_ELEMENTS(log_domains)(sizeof (log_domains) / sizeof ((log_domains)[0])); i++)
500 g_log_set_handler (log_domains[i],
501 G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
502 log_handler, NULL((void*)0));
503
504#endif
505
506 if (g_getenv ("CROMA_G_FATAL_WARNINGS") != NULL((void*)0))
507 g_log_set_always_fatal (G_LOG_LEVEL_MASK);
508
509 meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE(0));
510
511 /* Try to find some theme that'll work if the theme preference
512 * doesn't exist. First try Simple (the default theme) then just
513 * try anything in the themes directory.
514 */
515 if (!meta_ui_have_a_theme ())
516 meta_ui_set_current_theme ("Simple", FALSE(0));
517
518 if (!meta_ui_have_a_theme ())
519 {
520 const char *dir_entry = NULL((void*)0);
521 GError *err = NULL((void*)0);
522 GDir *themes_dir = NULL((void*)0);
523
524 if (!(themes_dir = g_dir_open (CROMA_DATADIR"/usr/local/share""/themes", 0, &err)))
525 {
526 meta_fatal (_("Failed to scan themes directory: %s\n")dgettext ("croma", "Failed to scan themes directory: %s\n"), err->message);
527 g_error_free (err);
528 }
529 else
530 {
531 while (((dir_entry = g_dir_read_name (themes_dir)) != NULL((void*)0)) &&
532 (!meta_ui_have_a_theme ()))
533 {
534 meta_ui_set_current_theme (dir_entry, FALSE(0));
535 }
536
537 g_dir_close (themes_dir);
538 }
539 }
540
541 if (!meta_ui_have_a_theme ())
542 meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n")dgettext ("croma", "Could not find a theme! Be sure %s exists and contains the usual themes.\n"
)
,
543 CROMA_DATADIR"/usr/local/share""/themes");
544
545 /* Connect to SM as late as possible - but before managing display,
546 * or we might try to manage a window before we have the session
547 * info
548 */
549 if (!meta_args.disable_sm)
550 {
551 if (meta_args.client_id == NULL((void*)0))
552 {
553 const gchar *desktop_autostart_id;
554
555 desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
556
557 if (desktop_autostart_id != NULL((void*)0))
558 meta_args.client_id = g_strdup (desktop_autostart_id);
559 }
560
561 /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
562 * use the same client id. */
563 g_unsetenv ("DESKTOP_AUTOSTART_ID");
564
565 meta_session_init (meta_args.client_id, meta_args.save_file);
566 }
567 /* Free memory possibly allocated by the argument parsing which are
568 * no longer needed.
569 */
570 g_free (meta_args.save_file);
571 g_free (meta_args.display_name);
572 g_free (meta_args.client_id);
573
574 if (meta_args.composite || meta_args.no_composite)
575 meta_prefs_set_force_compositing_manager (meta_args.composite);
576
577 if (meta_args.no_force_fullscreen)
578 meta_prefs_set_force_fullscreen (FALSE(0));
579
580 if (!meta_display_open ())
581 meta_exit (META_EXIT_ERROR);
582
583 g_main_loop_run (meta_main_loop);
584
585 meta_finalize ();
586
587 if (meta_restart_after_quit)
588 {
589 GError *err;
590
591 err = NULL((void*)0);
592 if (!g_spawn_async (NULL((void*)0),
593 argv,
594 NULL((void*)0),
595 G_SPAWN_SEARCH_PATH,
596 NULL((void*)0),
597 NULL((void*)0),
598 NULL((void*)0),
599 &err))
600 {
601 meta_fatal (_("Failed to restart: %s\n")dgettext ("croma", "Failed to restart: %s\n"),
602 err->message);
603 g_error_free (err); /* not reached anyhow */
604 meta_exit_code = META_EXIT_ERROR;
605 }
606 }
607
608 return meta_exit_code;
609}
610
611/**
612 * Stops Croma. This tells the event loop to stop processing; it is rather
613 * dangerous to use this rather than meta_restart() because this will leave
614 * the user with no window manager. We generally do this only if, for example,
615 * the session manager asks us to; we assume the session manager knows what
616 * it's talking about.
617 *
618 * \param code The success or failure code to return to the calling process.
619 */
620void
621meta_quit (MetaExitCode code)
622{
623 meta_exit_code = code;
624
625 if (g_main_loop_is_running (meta_main_loop))
626 g_main_loop_quit (meta_main_loop);
627}
628
629/**
630 * Restarts Croma. In practice, this tells the event loop to stop
631 * processing, having first set the meta_restart_after_quit flag which
632 * tells Croma to spawn an identical copy of itself before quitting.
633 * This happens on receipt of a _CROMA_RESTART_MESSAGE client event.
634 */
635void
636meta_restart (void)
637{
638 meta_restart_after_quit = TRUE(!(0));
639 meta_quit (META_EXIT_SUCCESS);
640}
641
642/**
643 * Called on pref changes. (One of several functions of its kind and purpose.)
644 *
645 * \bug Why are these particular prefs handled in main.c and not others?
646 * Should they be?
647 *
648 * \param pref Which preference has changed
649 * \param data Arbitrary data (which we ignore)
650 */
651static void
652prefs_changed_callback (MetaPreference pref,
653 gpointer data)
654{
655 switch (pref)
656 {
657 case META_PREF_THEME:
658 meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE(0));
659 meta_display_retheme_all ();
660 break;
661
662 case META_PREF_CURSOR_THEME:
663 case META_PREF_CURSOR_SIZE:
664 meta_display_set_cursor_theme (meta_prefs_get_cursor_theme (),
665 meta_prefs_get_cursor_size ());
666 break;
667 case META_PREF_ICON_SIZE:
668 meta_invalidate_all_icons();
669 break;
670 default:
671 /* handled elsewhere or otherwise */
672 break;
673 }
674}