1 /* $Id$ */
2 /*-
3 * Copyright (c) 2003-2006 Benedikt Meurer <benny@xfce.org>
4 * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu>
5 * All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301 USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #ifdef HAVE_ERRNO_H
28 #include <errno.h>
29 #endif
30 #ifdef HAVE_MEMORY_H
31 #include <memory.h>
32 #endif
33 #ifdef HAVE_STDIO_H
34 #include <stdio.h>
35 #endif
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 #ifdef HAVE_STRING_H
40 #include <string.h>
41 #endif
42 #ifdef HAVE_TIME_H
43 #include <time.h>
44 #endif
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #ifdef HAVE_SYS_TYPES_H
49 #include <sys/types.h>
50 #endif
51 #ifdef HAVE_SIGNAL_H
52 #include <signal.h>
53 #endif
54
55 #include <glib/gstdio.h>
56 #include <gdk/gdkx.h>
57 #include <libxfce4ui/libxfce4ui.h>
58
59 #include <libxfsm/xfsm-util.h>
60
61 #include <xfce4-session/xfsm-compat-gnome.h>
62 #include <xfce4-session/xfsm-compat-kde.h>
63 #include <xfce4-session/xfsm-global.h>
64 #include <xfce4-session/xfsm-manager.h>
65 #include <xfce4-session/xfsm-systemd.h>
66
67 #include <xfce4-session/xfsm-startup.h>
68
69
70 typedef struct
71 {
72 XfsmManager *manager;
73 XfsmProperties *properties;
74 } XfsmStartupData;
75
76 static gboolean xfsm_startup_session_next_prio_group (XfsmManager *manager);
77
78 static void xfsm_startup_data_free (XfsmStartupData *sdata);
79 static void xfsm_startup_child_watch (GPid pid,
80 gint status,
81 gpointer user_data);
82 static gboolean xfsm_startup_timeout (gpointer data);
83
84 static void xfsm_startup_handle_failed_startup (XfsmProperties *properties,
85 XfsmManager *manager);
86
87
88 static pid_t running_sshagent = -1;
89 static pid_t running_gpgagent = -1;
90 static gboolean gpgagent_ssh_enabled = FALSE;
91
92
93
94 static pid_t
xfsm_gpg_agent_pid(const gchar * gpg_agent_info)95 xfsm_gpg_agent_pid (const gchar *gpg_agent_info)
96 {
97 pid_t pid = -1;
98 gchar **fields;
99
100 if (gpg_agent_info == NULL || *gpg_agent_info == '\0')
101 return -1;
102
103 fields = g_strsplit (gpg_agent_info, ":", 3);
104 if (fields != NULL)
105 {
106 /* second field of GPG_AGENT_INFO is a PID */
107 pid = atoi (fields[1]);
108 g_strfreev (fields);
109 }
110
111 return pid;
112 }
113
114
115
116 static pid_t
xfsm_ssh_agent_pid(const gchar * ssh_agent_pid)117 xfsm_ssh_agent_pid (const gchar *ssh_agent_pid)
118 {
119 if (ssh_agent_pid == NULL || *ssh_agent_pid == '\0')
120 return -1;
121
122 return atoi (ssh_agent_pid);
123 }
124
125
126
127 static pid_t
xfsm_startup_init_agent(const gchar * cmd,const gchar * agent,gboolean want_pid)128 xfsm_startup_init_agent (const gchar *cmd,
129 const gchar *agent,
130 gboolean want_pid)
131 {
132 gchar *cmdoutput = NULL;
133 GError *error = NULL;
134 gchar **lines;
135 guint i;
136 gchar *p, *t;
137 gchar *variable, *value;
138 pid_t pid = -1;
139
140 if (g_spawn_command_line_sync (cmd, &cmdoutput, NULL, NULL, &error))
141 {
142 if (G_UNLIKELY (cmdoutput == NULL))
143 {
144 g_message ("%s returned no variables to stdout", agent);
145 return -1;
146 }
147
148 lines = g_strsplit (cmdoutput, "\n", -1);
149 g_assert (lines != NULL);
150 for (i = 0; lines[i] != NULL; i++)
151 {
152 p = strchr (lines[i], '=');
153 if (G_UNLIKELY (p == NULL))
154 continue;
155 t = strchr (p + 1, ';');
156 if (G_UNLIKELY (t == NULL))
157 continue;
158
159 variable = g_strndup (lines[i], p - lines[i]);
160 value = g_strndup (p + 1, t - p - 1);
161
162 /* try to get agent pid from the variable */
163 if (want_pid && pid <= 0)
164 {
165 if (g_strcmp0 (variable, "SSH_AGENT_PID") == 0)
166 pid = xfsm_ssh_agent_pid (value);
167 else if (g_strcmp0 (variable, "GPG_AGENT_INFO") == 0)
168 pid = xfsm_gpg_agent_pid (value);
169 }
170
171 g_setenv (variable, value, TRUE);
172
173 g_free (variable);
174 g_free (value);
175 }
176 g_strfreev (lines);
177 }
178 else
179 {
180 g_warning ("Failed to spawn %s: %s", agent, error->message);
181 g_error_free (error);
182
183 return -1;
184 }
185
186 g_free (cmdoutput);
187
188 if (!want_pid)
189 pid = 1;
190
191 if (pid <= 0)
192 g_warning ("%s returned no PID in the variables", agent);
193
194 return pid;
195 }
196
197
xfsm_gpg_agent_shutdown(gboolean quiet)198 static void xfsm_gpg_agent_shutdown(gboolean quiet)
199 {
200 GError *error = NULL;
201
202 g_spawn_command_line_sync ("gpgconf --kill gpg-agent",
203 NULL, NULL, NULL, &error);
204 if (error)
205 {
206 if (!quiet)
207 g_warning ("failed to kill gpg-agent via gpgconf, error was %s",
208 error->message);
209 g_error_free (error);
210 }
211 }
212
213
214 void
xfsm_startup_init(XfconfChannel * channel)215 xfsm_startup_init (XfconfChannel *channel)
216 {
217 gchar *ssh_agent;
218 gchar *ssh_agent_path = NULL;
219 gchar *gpg_agent_path = NULL;
220 gchar *cmd;
221 gchar *cmdoutput = NULL;
222 GError *error = NULL;
223 pid_t agentpid;
224 gboolean gnome_keyring_found;
225
226 /* if GNOME compatibility is enabled and gnome-keyring-daemon
227 * is found, skip the gpg/ssh agent startup and wait for
228 * gnome-keyring, which is probably what the user wants */
229 if (xfconf_channel_get_bool (channel, "/compat/LaunchGNOME", FALSE))
230 {
231 cmd = g_find_program_in_path ("gnome-keyring-daemon");
232 gnome_keyring_found = (cmd != NULL);
233 g_free (cmd);
234
235 if (gnome_keyring_found)
236 {
237 g_print ("xfce4-session: %s\n",
238 "GNOME compatibility is enabled and gnome-keyring-daemon is "
239 "found on the system. Skipping gpg/ssh-agent startup.");
240 return;
241 }
242 }
243
244 if (xfconf_channel_get_bool (channel, "/startup/gpg-agent/enabled", TRUE))
245 {
246 gpg_agent_path = g_find_program_in_path ("gpg-agent");
247 if (gpg_agent_path == NULL)
248 g_printerr ("xfce4-session: %s\n",
249 "No GPG agent found");
250 }
251
252 if (xfconf_channel_get_bool (channel, "/startup/ssh-agent/enabled", TRUE))
253 {
254 ssh_agent = xfconf_channel_get_string (channel, "/startup/ssh-agent/type", NULL);
255
256 if (ssh_agent == NULL
257 || g_strcmp0 (ssh_agent, "ssh-agent") == 0)
258 {
259 ssh_agent_path = g_find_program_in_path ("ssh-agent");
260 if (ssh_agent_path == NULL)
261 g_printerr ("xfce4-session: %s\n",
262 "No SSH authentication agent found");
263 }
264 else if (g_strcmp0 (ssh_agent, "gpg-agent") == 0)
265 {
266 if (gpg_agent_path != NULL)
267 gpgagent_ssh_enabled = TRUE;
268 else
269 g_printerr ("xfce4-session: %s\n", "gpg-agent is configured as SSH agent, "
270 "but gpg-agent is disabled or not found");
271 }
272 else
273 {
274 g_message ("Unknown SSH authentication agent \"%s\" set", ssh_agent);
275 }
276 g_free (ssh_agent);
277 }
278
279 if (G_LIKELY (ssh_agent_path != NULL || gpgagent_ssh_enabled))
280 {
281 agentpid = xfsm_ssh_agent_pid (g_getenv ("SSH_AGENT_PID"));
282
283 /* check if the pid is still responding (ie not stale) */
284 if (agentpid > 0 && kill (agentpid, 0) == 0)
285 {
286 g_message ("SSH authentication agent is already running");
287
288 gpgagent_ssh_enabled = FALSE;
289 g_free (ssh_agent_path);
290 ssh_agent_path = NULL;
291 }
292 else
293 {
294 g_unsetenv ("SSH_AGENT_PID");
295 g_unsetenv ("SSH_AUTH_SOCK");
296 }
297
298 if (ssh_agent_path != NULL)
299 {
300 cmd = g_strdup_printf ("%s -s", ssh_agent_path);
301 /* keep this around for shutdown */
302 running_sshagent = xfsm_startup_init_agent (cmd, "ssh-agent", TRUE);
303 g_free (cmd);
304
305 /* update dbus environment */
306 if (LOGIND_RUNNING())
307 {
308 cmd = g_strdup_printf ("%s", "dbus-update-activation-environment --systemd SSH_AUTH_SOCK");
309 }
310 else
311 {
312 cmd = g_strdup_printf ("%s", "dbus-update-activation-environment SSH_AUTH_SOCK");
313 }
314 g_spawn_command_line_sync (cmd, &cmdoutput, NULL, NULL, &error);
315
316 if (error)
317 {
318 g_warning ("failed to call dbus-update-activation-environment. Output was %s, error was %s",
319 cmdoutput, error->message);
320 }
321
322 g_free (cmd);
323 g_free (ssh_agent_path);
324 g_clear_pointer (&cmdoutput, g_free);
325 g_clear_error (&error);
326 }
327 }
328
329 if (G_LIKELY (gpg_agent_path != NULL))
330 {
331 xfsm_gpg_agent_shutdown (TRUE);
332 {
333 gboolean want_pid;
334 gchar *cmd_tmp;
335 gchar *envfile;
336
337 g_unsetenv ("GPG_AGENT_INFO");
338
339 envfile = xfce_resource_save_location (XFCE_RESOURCE_CACHE, "gpg-agent-info", FALSE);
340
341 cmd_tmp = g_strdup_printf ("%s --sh --daemon%s", gpg_agent_path,
342 gpgagent_ssh_enabled ?
343 " --enable-ssh-support" : "");
344
345 cmd = cmd_tmp;
346 want_pid = FALSE;
347
348 /* keep this around for shutdown */
349 running_gpgagent = xfsm_startup_init_agent (cmd, "gpg-agent",
350 want_pid);
351
352 g_free (cmd);
353 g_free (envfile);
354 }
355
356 g_free (gpg_agent_path);
357 }
358 }
359
360
361
362 void
xfsm_startup_shutdown(void)363 xfsm_startup_shutdown (void)
364 {
365 if (running_sshagent > 0)
366 {
367 if (kill (running_sshagent, SIGTERM) == 0)
368 {
369 /* make sure the env values are unset */
370 g_unsetenv ("SSH_AGENT_PID");
371 g_unsetenv ("SSH_AUTH_SOCK");
372 }
373 else
374 {
375 g_warning ("Failed to kill ssh-agent with pid %d", running_sshagent);
376 }
377 }
378
379 if (running_gpgagent > 0)
380 {
381 xfsm_gpg_agent_shutdown (FALSE);
382 }
383 }
384
385
386
387 static void
xfsm_startup_autostart(XfsmManager * manager)388 xfsm_startup_autostart (XfsmManager *manager)
389 {
390 xfsm_launch_desktop_files_on_login (FALSE);
391 }
392
393
394
395 void
xfsm_startup_foreign(XfsmManager * manager)396 xfsm_startup_foreign (XfsmManager *manager)
397 {
398 if (xfsm_manager_get_compat_startup(manager, XFSM_MANAGER_COMPAT_KDE))
399 xfsm_compat_kde_startup ();
400
401 if (xfsm_manager_get_compat_startup(manager, XFSM_MANAGER_COMPAT_GNOME))
402 xfsm_compat_gnome_startup ();
403 }
404
405
406
407 static void
xfsm_startup_at_set_gtk_modules(void)408 xfsm_startup_at_set_gtk_modules (void)
409 {
410 const gchar *old;
411 gchar **modules;
412 guint i;
413 gboolean found_gail = FALSE;
414 gboolean found_atk_bridge = FALSE;
415 GString *new;
416
417 old = g_getenv ("GTK_MODULES");
418 if (old != NULL && *old != '\0')
419 {
420 /* check which modules are already loaded */
421 modules = g_strsplit (old, ":", -1);
422 for (i = 0; modules[i] != NULL; i++)
423 {
424 if (strcmp (modules[i], "gail") == 0)
425 found_gail = TRUE;
426 else if (strcmp (modules[i], "atk-bridge") == 0)
427 found_atk_bridge = TRUE;
428 }
429 g_strfreev (modules);
430
431 if (!found_gail || !found_atk_bridge)
432 {
433 /* append modules to old value */
434 new = g_string_new (old);
435 if (!found_gail)
436 new = g_string_append (new, ":gail");
437 if (!found_atk_bridge)
438 new = g_string_append (new, ":atk-bridge");
439
440 g_setenv ("GTK_MODULES", new->str, TRUE);
441 g_string_free (new, TRUE);
442 }
443 }
444 else
445 {
446 g_setenv ("GTK_MODULES", "gail:atk-bridge", TRUE);
447 }
448 }
449
450
451 static gboolean
xfsm_startup_at_spi_ior_set(void)452 xfsm_startup_at_spi_ior_set (void)
453 {
454 Atom AT_SPI_IOR;
455 GdkDisplay *display;
456 Atom actual_type;
457 gint actual_format;
458 guchar *data = NULL;
459 gulong nitems;
460 gulong leftover;
461
462 display = gdk_display_get_default ();
463 AT_SPI_IOR = XInternAtom (GDK_DISPLAY_XDISPLAY (display), "AT_SPI_IOR", False);
464 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
465 XDefaultRootWindow (GDK_DISPLAY_XDISPLAY (display)),
466 AT_SPI_IOR, 0L,
467 (long) BUFSIZ, False,
468 (Atom) 31, &actual_type, &actual_format,
469 &nitems, &leftover, &data);
470
471 if (data == NULL)
472 return FALSE;
473 XFree (data);
474
475 return TRUE;
476 }
477
478
479 static void
xfsm_startup_at(XfsmManager * manager)480 xfsm_startup_at (XfsmManager *manager)
481 {
482 gint n, i;
483
484 /* start at-spi-dbus-bus and/or at-spi-registryd */
485 n = xfsm_launch_desktop_files_on_login (TRUE);
486
487 if (n > 0)
488 {
489 xfsm_startup_at_set_gtk_modules ();
490
491 /* wait for 2 seconds until the at-spi registered, not very nice
492 * but required to properly start an accessible desktop */
493 for (i = 0; i < 10; i++)
494 {
495 if (xfsm_startup_at_spi_ior_set ())
496 break;
497 xfsm_verbose ("Waiting for at-spi to register...\n");
498 g_usleep (G_USEC_PER_SEC / 5);
499 }
500 }
501 else
502 {
503 g_warning ("No assistive technology service provider was started!");
504 }
505 }
506
507
508 void
xfsm_startup_begin(XfsmManager * manager)509 xfsm_startup_begin (XfsmManager *manager)
510 {
511 /* start assistive technology before anything else */
512 if (xfsm_manager_get_start_at (manager))
513 xfsm_startup_at (manager);
514
515 if (xfsm_manager_get_use_failsafe_mode (manager))
516 xfsm_verbose ("Starting the session in failsafe mode.\n");
517
518 xfsm_startup_session_continue (manager);
519 }
520
521
522 gboolean
xfsm_startup_start_properties(XfsmProperties * properties,XfsmManager * manager)523 xfsm_startup_start_properties (XfsmProperties *properties,
524 XfsmManager *manager)
525 {
526 XfsmStartupData *child_watch_data;
527 XfsmStartupData *startup_timeout_data;
528 gchar **restart_command;
529 gchar **argv;
530 gint argc;
531 gint n;
532 const gchar *current_directory;
533 GPid pid;
534 GError *error = NULL;
535
536 /* release any possible old resources related to a previous startup */
537 xfsm_properties_set_default_child_watch (properties);
538
539 /* generate the argument vector for the application (expanding variables) */
540 restart_command = xfsm_properties_get_strv (properties, SmRestartCommand);
541 argc = g_strv_length (restart_command);
542 argv = g_new (gchar *, argc + 1);
543 for (n = 0; n < argc; ++n)
544 argv[n] = xfce_expand_variables (restart_command[n], NULL);
545 argv[n] = NULL;
546
547 current_directory = xfsm_properties_get_string (properties, SmCurrentDirectory);
548
549 if (!g_spawn_async (current_directory,
550 argv, NULL,
551 G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
552 NULL, NULL,
553 &pid, &error))
554 {
555 g_warning ("Unable to launch \"%s\": %s",
556 *argv, error->message);
557 g_error_free (error);
558 g_strfreev (argv);
559
560 return FALSE;
561 }
562
563 /* Don't waste time if we're not debugging, but if we are print the
564 * command + the arguments */
565 if (xfsm_is_verbose_enabled ())
566 {
567 gchar *command = g_strjoinv (" ", argv);
568 xfsm_verbose ("Launching command \"%s\" with PID %d\n", command, (gint) pid);
569 g_free (command);
570 }
571
572 g_strfreev (argv);
573
574 properties->pid = pid;
575
576 /* set a watch to make sure the child doesn't quit before registering */
577 child_watch_data = g_new0 (XfsmStartupData, 1);
578 child_watch_data->manager = g_object_ref (manager);
579 child_watch_data->properties = properties;
580 child_watch_data->properties->child_watch_id =
581 g_child_watch_add_full (G_PRIORITY_LOW, properties->pid,
582 xfsm_startup_child_watch, child_watch_data,
583 (GDestroyNotify) xfsm_startup_data_free);
584
585 /* set a timeout -- client must register in a a certain amount of time
586 * or it's assumed to be broken/have issues. */
587 startup_timeout_data = g_new (XfsmStartupData, 1);
588 startup_timeout_data->manager = g_object_ref (manager);
589 startup_timeout_data->properties = properties;
590 properties->startup_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
591 STARTUP_TIMEOUT,
592 xfsm_startup_timeout,
593 startup_timeout_data,
594 (GDestroyNotify) xfsm_startup_data_free);
595
596 return TRUE;
597 }
598
599
600 void
xfsm_startup_session_continue(XfsmManager * manager)601 xfsm_startup_session_continue (XfsmManager *manager)
602 {
603 GQueue *pending_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_PENDING_PROPS);
604 gboolean client_started = FALSE;
605
606 /* try to start some clients. if we fail to start anything in the current
607 * priority group, move right to the next one. if we *did* start something,
608 * the failed/registered handlers will take care of moving us on to the
609 * next priority group */
610 while (client_started == FALSE && g_queue_peek_head (pending_properties) != NULL)
611 client_started = xfsm_startup_session_next_prio_group (manager);
612
613 if (G_UNLIKELY (client_started == FALSE && g_queue_peek_head (pending_properties) == NULL))
614 {
615 /* we failed to start anything, and we don't have anything else,
616 * to start, so just move on to the autostart items and signal
617 * the manager that we're finished */
618 xfsm_verbose ("Nothing started and nothing to start, moving to autostart items\n");
619 xfsm_startup_autostart (manager);
620 xfsm_manager_signal_startup_done (manager);
621 }
622 }
623
624
625 /* returns TRUE if we started anything, FALSE if we didn't */
626 static gboolean
xfsm_startup_session_next_prio_group(XfsmManager * manager)627 xfsm_startup_session_next_prio_group (XfsmManager *manager)
628 {
629 GQueue *pending_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_PENDING_PROPS);
630 GQueue *starting_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_STARTING_PROPS);
631 XfsmProperties *properties;
632 gint cur_prio_group;
633 gboolean client_started = FALSE;
634
635 properties = (XfsmProperties *) g_queue_peek_head (pending_properties);
636 if (properties == NULL)
637 return FALSE;
638
639 cur_prio_group = xfsm_properties_get_uchar (properties, GsmPriority, 50);
640
641 xfsm_verbose ("Starting apps in prio group %d\n (%d)", cur_prio_group, g_queue_get_length (pending_properties));
642
643 while ((properties = g_queue_pop_head (pending_properties)))
644 {
645 /* quit if we've hit all the clients in the current prio group */
646 if (xfsm_properties_get_uchar (properties, GsmPriority, 50) != cur_prio_group)
647 {
648 /* we're not starting this one yet; put it back */
649 g_queue_push_head (pending_properties, properties);
650 break;
651 }
652
653 /* as clients cannot be uniquely identified in failsafe mode we at least count
654 how many per priority group have registered */
655 if (xfsm_manager_get_use_failsafe_mode (manager))
656 xfsm_manager_increase_failsafe_pending_clients (manager);
657
658 if (G_LIKELY (xfsm_startup_start_properties (properties, manager)))
659 {
660 g_queue_push_tail (starting_properties, properties);
661 client_started = TRUE;
662 }
663 else
664 {
665 /* if starting the app failed, let the manager handle it */
666 if (xfsm_manager_handle_failed_properties (manager, properties) == FALSE)
667 xfsm_properties_free (properties);
668 }
669 }
670
671 return client_started;
672 }
673
674
675 static void
xfsm_startup_data_free(XfsmStartupData * sdata)676 xfsm_startup_data_free (XfsmStartupData *sdata)
677 {
678 g_object_unref (sdata->manager);
679 g_free (sdata);
680 }
681
682
683 static void
xfsm_startup_child_watch(GPid pid,gint status,gpointer user_data)684 xfsm_startup_child_watch (GPid pid,
685 gint status,
686 gpointer user_data)
687 {
688 XfsmStartupData *cwdata = user_data;
689 GQueue *starting_properties;
690
691 xfsm_verbose ("Client Id = %s, PID %d exited with status %d\n",
692 cwdata->properties->client_id, (gint)pid, status);
693
694 cwdata->properties->child_watch_id = 0;
695 cwdata->properties->pid = -1;
696
697 starting_properties = xfsm_manager_get_queue (cwdata->manager, XFSM_MANAGER_QUEUE_STARTING_PROPS);
698 if (g_queue_find (starting_properties, cwdata->properties) != NULL)
699 {
700 xfsm_verbose ("Client Id = %s died while starting up\n",
701 cwdata->properties->client_id);
702 xfsm_startup_handle_failed_startup (cwdata->properties, cwdata->manager);
703 }
704
705 /* NOTE: cwdata->properties could have been freed by
706 * xfsm_startup_handle_failed_startup() above, so don't try to access
707 * any of its members here. */
708
709 g_spawn_close_pid (pid);
710 }
711
712
713 static gboolean
xfsm_startup_timeout(gpointer data)714 xfsm_startup_timeout (gpointer data)
715 {
716 XfsmStartupData *stdata = data;
717
718 xfsm_verbose ("Client Id = %s failed to register in time\n",
719 stdata->properties->client_id);
720
721 stdata->properties->startup_timeout_id = 0;
722 xfsm_startup_handle_failed_startup (stdata->properties, stdata->manager);
723
724 return FALSE;
725 }
726
727
728 static void
xfsm_startup_handle_failed_startup(XfsmProperties * properties,XfsmManager * manager)729 xfsm_startup_handle_failed_startup (XfsmProperties *properties,
730 XfsmManager *manager)
731 {
732 GQueue *starting_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_STARTING_PROPS);
733
734 xfsm_verbose ("Client Id = %s failed to start\n", properties->client_id);
735
736 /* if our timer hasn't run out yet, kill it */
737 if (properties->startup_timeout_id > 0)
738 {
739 g_source_remove (properties->startup_timeout_id);
740 properties->startup_timeout_id = 0;
741 }
742
743 xfsm_properties_set_default_child_watch (properties);
744
745 /* not starting anymore, so remove it from the list. tell the manager
746 * it failed, and let it do its thing. */
747 g_queue_remove (starting_properties, properties);
748 if (xfsm_manager_handle_failed_properties (manager, properties) == FALSE)
749 xfsm_properties_free (properties);
750
751 if (g_queue_peek_head (starting_properties) == NULL
752 && xfsm_manager_get_state (manager) == XFSM_MANAGER_STARTUP)
753 {
754 /* everything has finished starting or failed; continue startup */
755 xfsm_startup_session_continue (manager);
756 }
757 }
758