7 #include <glib/gstdio.h>
10 #include <gio/gunixsocketaddress.h>
14 /* Timeout in ms waiting for the status we expect */
15 static int status_timeout_ms = 4000;
17 /* Timeout in ms to wait for SIGTERM to be handled by a child process */
18 #define KILL_TIMEOUT 2000
20 static gchar *test_runner_command;
21 static gchar *config_path;
22 static GKeyFile *config;
23 static GSocket *status_socket = NULL;
24 static gchar *status_socket_name = NULL;
25 static GList *statuses = NULL;
31 static GList *script = NULL;
32 static guint status_timeout = 0;
33 static gchar *temp_dir = NULL;
34 static int service_count;
40 static Process *lightdm_process = NULL;
41 static GHashTable *children = NULL;
42 static gboolean stop = FALSE;
43 static gint exit_status = 0;
44 static GDBusConnection *accounts_connection = NULL;
45 static GDBusNodeInfo *accounts_info;
46 static GDBusNodeInfo *user_info;
52 gchar *home_directory;
60 gboolean has_messages;
63 static GList *accounts_users = NULL;
64 static void handle_user_call (GDBusConnection *connection,
66 const gchar *object_path,
67 const gchar *interface_name,
68 const gchar *method_name,
70 GDBusMethodInvocation *invocation,
72 static GVariant *handle_user_get_property (GDBusConnection *connection,
74 const gchar *object_path,
75 const gchar *interface_name,
76 const gchar *property_name,
79 static const GDBusInterfaceVTable user_vtable =
82 handle_user_get_property,
84 static GDBusNodeInfo *ck_session_info;
92 static GList *ck_sessions = NULL;
93 static gint ck_session_index = 0;
94 static void handle_ck_session_call (GDBusConnection *connection,
96 const gchar *object_path,
97 const gchar *interface_name,
98 const gchar *method_name,
100 GDBusMethodInvocation *invocation,
102 static const GDBusInterfaceVTable ck_session_vtable =
104 handle_ck_session_call,
111 gboolean can_graphical;
112 gboolean can_multi_session;
115 static GList *login1_seats = NULL;
117 static Login1Seat *add_login1_seat (GDBusConnection *connection, const gchar *id, gboolean can_graphical, gboolean can_multi_session, gboolean emit_signal);
118 static void remove_login1_seat (GDBusConnection *connection, const gchar *id);
127 static GList *login1_sessions = NULL;
128 static gint login1_session_index = 0;
135 static GList *status_clients = NULL;
137 static void ready (void);
138 static void quit (int status);
139 static void check_status (const gchar *status);
140 static AccountsUser *get_accounts_user_by_uid (guint uid);
141 static AccountsUser *get_accounts_user_by_name (const gchar *username);
142 static void accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal);
145 kill_timeout_cb (gpointer data)
147 Process *process = data;
149 process->kill_timeout = 0;
151 if (getenv ("DEBUG"))
152 g_print ("Sending SIGKILL to process %d\n", process->pid);
153 kill (process->pid, SIGKILL);
159 stop_process (Process *process)
161 if (process->kill_timeout != 0)
164 if (getenv ("DEBUG"))
165 g_print ("Sending SIGTERM to process %d\n", process->pid);
166 kill (process->pid, SIGTERM);
167 process->kill_timeout = g_timeout_add (KILL_TIMEOUT, kill_timeout_cb, process);
171 process_exit_cb (GPid pid, gint status, gpointer data)
176 if (getenv ("DEBUG"))
178 if (WIFEXITED (status))
179 g_print ("Process %d exited with status %d\n", pid, WEXITSTATUS (status));
181 g_print ("Process %d terminated with signal %d\n", pid, WTERMSIG (status));
184 if (lightdm_process && pid == lightdm_process->pid)
186 process = lightdm_process;
187 lightdm_process = NULL;
188 if (WIFEXITED (status))
189 status_text = g_strdup_printf ("RUNNER DAEMON-EXIT STATUS=%d", WEXITSTATUS (status));
191 status_text = g_strdup_printf ("RUNNER DAEMON-TERMINATE SIGNAL=%d", WTERMSIG (status));
192 check_status (status_text);
196 process = g_hash_table_lookup (children, GINT_TO_POINTER (pid));
199 g_hash_table_remove (children, GINT_TO_POINTER (pid));
202 if (process->kill_timeout)
203 g_source_remove (process->kill_timeout);
204 process->kill_timeout = 0;
206 /* Quit once all children have stopped */
212 watch_process (pid_t pid)
216 process = g_malloc0 (sizeof (Process));
218 process->kill_timeout = 0;
220 if (getenv ("DEBUG"))
221 g_print ("Watching process %d\n", process->pid);
222 g_child_watch_add (process->pid, process_exit_cb, NULL);
233 exit_status = status;
236 /* Stop all the children */
237 g_hash_table_iter_init (&iter, children);
242 if (!g_hash_table_iter_next (&iter, &key, &value))
245 stop_process ((Process *)value);
248 /* Don't quit until all children are stopped */
249 if (g_hash_table_size (children) > 0)
252 /* Stop the daemon */
255 stop_process (lightdm_process);
259 if (status_socket_name)
260 unlink (status_socket_name);
262 if (temp_dir && getenv ("DEBUG") == NULL)
264 gchar *command = g_strdup_printf ("rm -rf %s", temp_dir);
265 if (system (command))
266 perror ("Failed to delete temp directory");
273 fail (const gchar *event, const gchar *expected)
280 g_printerr ("Command line: %s", test_runner_command);
281 g_printerr ("Events:\n");
282 for (link = statuses; link; link = link->next)
283 g_printerr (" %s\n", (gchar *)link->data);
285 g_printerr (" %s\n", event);
287 g_printerr (" ^^^ expected \"%s\"\n", expected);
289 g_printerr ("^^^ expected nothing\n");
295 get_prefix (const gchar *text)
300 prefix = g_strdup (text);
301 for (i = 0; prefix[i] != '\0' && prefix[i] != ' '; i++);
308 get_script_line (const gchar *prefix)
312 for (link = script; link; link = link->next)
314 ScriptLine *line = link->data;
316 /* Ignore lines with other prefixes */
322 p = get_prefix (line->text);
323 matches = strcmp (prefix, p) == 0;
338 stop_loop (gpointer user_data)
340 g_main_loop_quit ((GMainLoop *)user_data);
341 return G_SOURCE_REMOVE;
345 handle_command (const gchar *command)
352 while (*c && !isspace (*c))
354 name = g_strdup_printf ("%.*s", (int) (c - command), command);
356 params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
360 gchar *param_name, *param_value;
365 while (*c && !isspace (*c) && *c != '=')
370 param_name = g_strdup_printf ("%.*s", (int) (c - start), start);
379 gboolean escaped = FALSE;
383 value = g_string_new ("");
390 g_string_append_c (value, '\\');
396 else if (!escaped && *c == '\"')
399 g_string_append_c (value, *c);
402 param_value = value->str;
403 g_string_free (value, FALSE);
410 while (*c && !isspace (*c))
412 param_value = g_strdup_printf ("%.*s", (int) (c - start), start);
416 param_value = g_strdup ("");
418 g_hash_table_insert (params, param_name, param_value);
421 if (strcmp (name, "START-DAEMON") == 0)
423 GString *command_line;
424 gchar **lightdm_argv;
426 GError *error = NULL;
428 command_line = g_string_new ("lightdm");
429 if (getenv ("DEBUG"))
430 g_string_append (command_line, " --debug");
431 g_string_append_printf (command_line, " --cache-dir %s/cache", temp_dir);
433 test_runner_command = g_strdup_printf ("PATH=%s LD_PRELOAD=%s LD_LIBRARY_PATH=%s LIGHTDM_TEST_ROOT=%s DBUS_SESSION_BUS_ADDRESS=%s %s\n",
434 g_getenv ("PATH"), g_getenv ("LD_PRELOAD"), g_getenv ("LD_LIBRARY_PATH"), g_getenv ("LIGHTDM_TEST_ROOT"), g_getenv ("DBUS_SESSION_BUS_ADDRESS"),
437 if (!g_shell_parse_argv (command_line->str, NULL, &lightdm_argv, &error))
439 g_warning ("Error parsing command line: %s", error->message);
442 g_clear_error (&error);
444 if (!g_spawn_async (NULL, lightdm_argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &lightdm_pid, &error))
446 g_warning ("Error launching LightDM: %s", error->message);
449 g_clear_error (&error);
450 lightdm_process = watch_process (lightdm_pid);
452 check_status ("RUNNER DAEMON-START");
454 else if (strcmp (name, "WAIT") == 0)
456 /* Use a main loop so that our DBus functions are still responsive */
457 GMainLoop *loop = g_main_loop_new (NULL, FALSE);
458 g_timeout_add_seconds (1, stop_loop, loop);
459 g_main_loop_run (loop);
460 g_main_loop_unref (loop);
462 else if (strcmp (name, "ADD-SEAT") == 0)
465 gboolean can_graphical, can_multi_session;
467 id = g_hash_table_lookup (params, "ID");
468 v = g_hash_table_lookup (params, "CAN-GRAPHICAL");
469 can_graphical = !v || strcmp (v, "TRUE") == 0;
470 v = g_hash_table_lookup (params, "CAN-MULTI-SESSION");
471 can_multi_session = !v || strcmp (v, "TRUE") == 0;
472 add_login1_seat (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL), id, can_graphical, can_multi_session, TRUE);
474 else if (strcmp (name, "REMOVE-SEAT") == 0)
477 id = g_hash_table_lookup (params, "ID");
478 remove_login1_seat (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL), id);
480 else if (strcmp (name, "LIST-SEATS") == 0)
482 GVariant *result, *value;
488 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
489 "org.freedesktop.DisplayManager",
490 "/org/freedesktop/DisplayManager",
491 "org.freedesktop.DBus.Properties",
493 g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Seats"),
494 G_VARIANT_TYPE ("(v)"),
495 G_DBUS_CALL_FLAGS_NONE,
500 status = g_string_new ("RUNNER LIST-SEATS SEATS=");
501 g_variant_get (result, "(v)", &value);
502 g_variant_get (value, "ao", &iter);
503 while (g_variant_iter_loop (iter, "&o", &path))
506 g_string_append (status, ",");
507 g_string_append (status, path);
510 g_variant_unref (value);
511 g_variant_unref (result);
513 check_status (status->str);
514 g_string_free (status, TRUE);
516 else if (strcmp (name, "LIST-SESSIONS") == 0)
518 GVariant *result, *value;
524 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
525 "org.freedesktop.DisplayManager",
526 "/org/freedesktop/DisplayManager",
527 "org.freedesktop.DBus.Properties",
529 g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"),
530 G_VARIANT_TYPE ("(v)"),
531 G_DBUS_CALL_FLAGS_NONE,
536 status = g_string_new ("RUNNER LIST-SESSIONS SESSIONS=");
537 g_variant_get (result, "(v)", &value);
538 g_variant_get (value, "ao", &iter);
539 while (g_variant_iter_loop (iter, "&o", &path))
542 g_string_append (status, ",");
543 g_string_append (status, path);
546 g_variant_unref (value);
547 g_variant_unref (result);
549 check_status (status->str);
550 g_string_free (status, TRUE);
552 else if (strcmp (name, "SEAT-CAN-SWITCH") == 0)
554 GVariant *result, *value;
557 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
558 "org.freedesktop.DisplayManager",
559 "/org/freedesktop/DisplayManager/Seat0",
560 "org.freedesktop.DBus.Properties",
562 g_variant_new ("(ss)", "org.freedesktop.DisplayManager.Seat", "CanSwitch"),
563 G_VARIANT_TYPE ("(v)"),
564 G_DBUS_CALL_FLAGS_NONE,
569 g_variant_get (result, "(v)", &value);
570 status = g_strdup_printf ("RUNNER SEAT-CAN-SWITCH CAN-SWITCH=%s", g_variant_get_boolean (value) ? "TRUE" : "FALSE");
571 g_variant_unref (value);
572 g_variant_unref (result);
573 check_status (status);
576 else if (strcmp (name, "SEAT-HAS-GUEST-ACCOUNT") == 0)
578 GVariant *result, *value;
581 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
582 "org.freedesktop.DisplayManager",
583 "/org/freedesktop/DisplayManager/Seat0",
584 "org.freedesktop.DBus.Properties",
586 g_variant_new ("(ss)", "org.freedesktop.DisplayManager.Seat", "HasGuestAccount"),
587 G_VARIANT_TYPE ("(v)"),
588 G_DBUS_CALL_FLAGS_NONE,
593 g_variant_get (result, "(v)", &value);
594 status = g_strdup_printf ("RUNNER SEAT-HAS-GUEST-ACCOUNT HAS-GUEST-ACCOUNT=%s", g_variant_get_boolean (value) ? "TRUE" : "FALSE");
595 g_variant_unref (value);
596 g_variant_unref (result);
597 check_status (status);
600 else if (strcmp (name, "SWITCH-TO-GREETER") == 0)
604 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
605 "org.freedesktop.DisplayManager",
606 "/org/freedesktop/DisplayManager/Seat0",
607 "org.freedesktop.DisplayManager.Seat",
609 g_variant_new ("()"),
610 G_VARIANT_TYPE ("()"),
611 G_DBUS_CALL_FLAGS_NONE,
617 check_status ("RUNNER SWITCH-TO-GREETER");
618 g_variant_unref (result);
621 check_status ("RUNNER SWITCH-TO-GREETER FAILED");
623 else if (strcmp (name, "SWITCH-TO-USER") == 0)
626 const gchar *username;
628 username = g_hash_table_lookup (params, "USERNAME");
629 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
630 "org.freedesktop.DisplayManager",
631 "/org/freedesktop/DisplayManager/Seat0",
632 "org.freedesktop.DisplayManager.Seat",
634 g_variant_new ("(ss)", username, ""),
635 G_VARIANT_TYPE ("()"),
636 G_DBUS_CALL_FLAGS_NONE,
643 status_text = g_strdup_printf ("RUNNER SWITCH-TO-USER USERNAME=%s", username);
644 check_status (status_text);
645 g_free (status_text);
646 g_variant_unref (result);
651 status_text = g_strdup_printf ("RUNNER SWITCH-TO-USER USERNAME=%s FAILED", username);
652 check_status (status_text);
653 g_free (status_text);
656 else if (strcmp (name, "SWITCH-TO-GUEST") == 0)
660 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
661 "org.freedesktop.DisplayManager",
662 "/org/freedesktop/DisplayManager/Seat0",
663 "org.freedesktop.DisplayManager.Seat",
665 g_variant_new ("(s)", ""),
666 G_VARIANT_TYPE ("()"),
667 G_DBUS_CALL_FLAGS_NONE,
673 check_status ("RUNNER SWITCH-TO-GUEST");
674 g_variant_unref (result);
677 check_status ("RUNNER SWITCH-TO-GUEST FAILED");
679 else if (strcmp (name, "STOP-DAEMON") == 0)
680 stop_process (lightdm_process);
681 // FIXME: Make generic RUN-COMMAND
682 else if (strcmp (name, "START-XSERVER") == 0)
684 gchar *xserver_args, *command_line;
688 GError *error = NULL;
690 xserver_args = g_hash_table_lookup (params, "ARGS");
693 command_line = g_strdup_printf ("%s/tests/src/X %s", BUILDDIR, xserver_args);
695 if (!g_shell_parse_argv (command_line, NULL, &argv, &error) ||
696 !g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &error))
698 g_printerr ("Error starting X server: %s", error->message);
703 process = watch_process (pid);
704 g_hash_table_insert (children, GINT_TO_POINTER (process->pid), process);
707 else if (strcmp (name, "START-VNC-CLIENT") == 0)
709 gchar *vnc_client_args, *command_line;
713 GError *error = NULL;
715 vnc_client_args = g_hash_table_lookup (params, "ARGS");
716 if (!vnc_client_args)
717 vnc_client_args = "";
718 command_line = g_strdup_printf ("%s/tests/src/vnc-client %s", BUILDDIR, vnc_client_args);
720 if (!g_shell_parse_argv (command_line, NULL, &argv, &error) ||
721 !g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &error))
723 g_printerr ("Error starting VNC client: %s", error->message);
728 process = watch_process (pid);
729 g_hash_table_insert (children, GINT_TO_POINTER (process->pid), process);
732 else if (strcmp (name, "ADD-USER") == 0)
734 gchar *status_text, *username;
737 username = g_hash_table_lookup (params, "USERNAME");
738 user = get_accounts_user_by_name (username);
740 accounts_user_set_hidden (user, FALSE, TRUE);
742 g_warning ("Unknown user %s", username);
744 status_text = g_strdup_printf ("RUNNER ADD-USER USERNAME=%s", username);
745 check_status (status_text);
746 g_free (status_text);
748 else if (strcmp (name, "UPDATE-USER") == 0)
750 GString *status_text;
753 GError *error = NULL;
755 status_text = g_string_new ("RUNNER UPDATE-USER USERNAME=");
757 username = g_hash_table_lookup (params, "USERNAME");
758 g_string_append (status_text, username);
759 user = get_accounts_user_by_name (username);
762 if (g_hash_table_lookup (params, "NAME"))
764 user->user_name = g_strdup (g_hash_table_lookup (params, "NAME"));
765 g_string_append_printf (status_text, " NAME=%s", user->user_name);
767 if (g_hash_table_lookup (params, "REAL-NAME"))
769 user->real_name = g_strdup (g_hash_table_lookup (params, "REAL-NAME"));
770 g_string_append_printf (status_text, " REAL-NAME=%s", user->real_name);
772 if (g_hash_table_lookup (params, "HOME-DIRECTORY"))
774 user->home_directory = g_strdup (g_hash_table_lookup (params, "HOME-DIRECTORY"));
775 g_string_append_printf (status_text, " HOME-DIRECTORY=%s", user->home_directory);
777 if (g_hash_table_lookup (params, "IMAGE"))
779 user->image = g_strdup (g_hash_table_lookup (params, "IMAGE"));
780 g_string_append_printf (status_text, " IMAGE=%s", user->image);
782 if (g_hash_table_lookup (params, "BACKGROUND"))
784 user->background = g_strdup (g_hash_table_lookup (params, "BACKGROUND"));
785 g_string_append_printf (status_text, " BACKGROUND=%s", user->background);
787 if (g_hash_table_lookup (params, "LANGUAGE"))
789 user->language = g_strdup (g_hash_table_lookup (params, "LANGUAGE"));
790 g_string_append_printf (status_text, " LANGUAGE=%s", user->language);
792 if (g_hash_table_lookup (params, "LAYOUTS"))
794 const gchar *value = g_hash_table_lookup (params, "LAYOUTS");
795 user->layouts = g_strsplit (value, ";", -1);
796 g_string_append_printf (status_text, " LAYOUTS=%s", value);
798 if (g_hash_table_lookup (params, "HAS-MESSAGES"))
800 user->has_messages = g_strcmp0 (g_hash_table_lookup (params, "HAS-MESSAGES"), "TRUE") == 0;
801 g_string_append_printf (status_text, " HAS-MESSAGES=%s", user->has_messages ? "TRUE" : "FALSE");
803 if (g_hash_table_lookup (params, "SESSION"))
805 user->xsession = g_strdup (g_hash_table_lookup (params, "SESSION"));
806 g_string_append_printf (status_text, " SESSION=%s", user->xsession);
810 g_warning ("Unknown user %s", username);
812 g_dbus_connection_emit_signal (accounts_connection,
815 "org.freedesktop.Accounts.User",
817 g_variant_new ("()"),
820 g_warning ("Failed to emit Changed: %s", error->message);
821 g_clear_error (&error);
823 check_status (status_text->str);
824 g_string_free (status_text, TRUE);
826 else if (strcmp (name, "DELETE-USER") == 0)
828 gchar *status_text, *username;
831 username = g_hash_table_lookup (params, "USERNAME");
832 user = get_accounts_user_by_name (username);
834 accounts_user_set_hidden (user, TRUE, TRUE);
836 g_warning ("Unknown user %s", username);
838 status_text = g_strdup_printf ("RUNNER DELETE-USER USERNAME=%s", username);
839 check_status (status_text);
840 g_free (status_text);
842 /* Forward to external processes */
843 else if (g_str_has_prefix (name, "SESSION-") ||
844 g_str_has_prefix (name, "GREETER-") ||
845 g_str_has_prefix (name, "XSERVER-") ||
846 strcmp (name, "UNITY-SYSTEM-COMPOSITOR") == 0)
849 for (link = status_clients; link; link = link->next)
851 StatusClient *client = link->data;
853 GError *error = NULL;
855 length = strlen (command);
856 if (g_socket_send (client->socket, (gchar *) &length, sizeof (length), NULL, &error) < 0 ||
857 g_socket_send (client->socket, command, strlen (command), NULL, &error) < 0)
858 g_printerr ("Failed to write to client socket: %s\n", error->message);
859 g_clear_error (&error);
864 g_printerr ("Unknown command '%s'\n", name);
869 g_hash_table_unref (params);
875 /* Stop daemon if requested */
880 /* Commands start with an asterisk */
881 line = get_script_line (NULL);
882 if (!line || line->text[0] != '*')
885 statuses = g_list_append (statuses, g_strdup (line->text));
888 handle_command (line->text + 1);
891 /* Stop at the end of the script */
892 if (get_script_line (NULL) == NULL)
897 status_timeout_cb (gpointer data)
901 line = get_script_line (NULL);
902 fail ("(timeout)", line ? line->text : NULL);
908 check_status (const gchar *status)
911 gboolean result = FALSE;
917 statuses = g_list_append (statuses, g_strdup (status));
919 if (getenv ("DEBUG"))
920 g_print ("%s\n", status);
922 /* Try and match against expected */
923 prefix = get_prefix (status);
924 line = get_script_line (prefix);
928 gchar *full_pattern = g_strdup_printf ("^%s$", line->text);
929 result = g_regex_match_simple (full_pattern, status, 0, 0);
930 g_free (full_pattern);
936 line = get_script_line (NULL);
937 fail (NULL, line ? line->text : NULL);
943 /* Restart timeout */
945 g_source_remove (status_timeout);
946 status_timeout = g_timeout_add (status_timeout_ms, status_timeout_cb, NULL);
952 status_message_cb (GSocket *socket, GIOCondition condition, StatusClient *client)
957 GError *error = NULL;
959 n_read = g_socket_receive (socket, (gchar *)&length, sizeof (length), NULL, &error);
961 n_read = g_socket_receive (socket, buffer, length, NULL, &error);
963 g_warning ("Error reading from socket: %s", error->message);
964 g_clear_error (&error);
967 status_clients = g_list_remove (status_clients, client);
968 g_object_unref (client->socket);
974 buffer[n_read] = '\0';
975 check_status (buffer);
982 status_connect_cb (gpointer data)
985 GError *error = NULL;
987 socket = g_socket_accept (status_socket, NULL, &error);
989 g_warning ("Failed to accept status connection: %s", error->message);
990 g_clear_error (&error);
993 StatusClient *client;
995 client = g_malloc0 (sizeof (StatusClient));
996 client->socket = socket;
997 client->source = g_socket_create_source (socket, G_IO_IN, NULL);
998 status_clients = g_list_append (status_clients, client);
1000 g_source_set_callback (client->source, (GSourceFunc) status_message_cb, client, NULL);
1001 g_source_attach (client->source, NULL);
1008 load_script (const gchar *filename)
1011 gchar *data, **lines;
1013 if (!g_file_get_contents (filename, &data, NULL, NULL))
1015 g_printerr ("Unable to load script: %s\n", filename);
1016 quit (EXIT_FAILURE);
1019 lines = g_strsplit (data, "\n", -1);
1022 /* Load lines with #? prefix as expected behaviour */
1023 for (i = 0; lines[i]; i++)
1025 gchar *text = g_strstrip (lines[i]);
1026 if (g_str_has_prefix (text, "#?"))
1029 line = g_malloc0 (sizeof (ScriptLine));
1030 line->text = g_strdup (text + 2);
1032 script = g_list_append (script, line);
1039 handle_upower_call (GDBusConnection *connection,
1040 const gchar *sender,
1041 const gchar *object_path,
1042 const gchar *interface_name,
1043 const gchar *method_name,
1044 GVariant *parameters,
1045 GDBusMethodInvocation *invocation,
1048 if (strcmp (method_name, "SuspendAllowed") == 0)
1050 check_status ("UPOWER SUSPEND-ALLOWED");
1051 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
1053 else if (strcmp (method_name, "Suspend") == 0)
1055 check_status ("UPOWER SUSPEND");
1056 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1058 else if (strcmp (method_name, "HibernateAllowed") == 0)
1060 check_status ("UPOWER HIBERNATE-ALLOWED");
1061 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
1063 else if (strcmp (method_name, "Hibernate") == 0)
1065 check_status ("UPOWER HIBERNATE");
1066 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1069 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1073 upower_name_acquired_cb (GDBusConnection *connection,
1077 const gchar *upower_interface =
1079 " <interface name='org.freedesktop.UPower'>"
1080 " <method name='SuspendAllowed'>"
1081 " <arg name='allowed' direction='out' type='b'/>"
1083 " <method name='Suspend'/>"
1084 " <method name='HibernateAllowed'>"
1085 " <arg name='allowed' direction='out' type='b'/>"
1087 " <method name='Hibernate'/>"
1090 static const GDBusInterfaceVTable upower_vtable =
1094 GDBusNodeInfo *upower_info;
1095 GError *error = NULL;
1097 upower_info = g_dbus_node_info_new_for_xml (upower_interface, &error);
1099 g_warning ("Failed to parse D-Bus interface: %s", error->message);
1100 g_clear_error (&error);
1103 g_dbus_connection_register_object (connection,
1104 "/org/freedesktop/UPower",
1105 upower_info->interfaces[0],
1110 g_warning ("Failed to register UPower service: %s", error->message);
1111 g_clear_error (&error);
1112 g_dbus_node_info_unref (upower_info);
1115 if (service_count == 0)
1120 start_upower_daemon (void)
1123 g_bus_own_name (G_BUS_TYPE_SYSTEM,
1124 "org.freedesktop.UPower",
1125 G_BUS_NAME_OWNER_FLAGS_NONE,
1126 upower_name_acquired_cb,
1134 open_ck_session (GDBusConnection *connection, GVariant *params)
1141 GError *error = NULL;
1143 session = g_malloc0 (sizeof (CKSession));
1144 ck_sessions = g_list_append (ck_sessions, session);
1146 cookie = g_string_new ("ck-cookie");
1147 g_variant_get (params, "a(sv)", &iter);
1148 while (g_variant_iter_loop (iter, "(&sv)", &name, &value))
1150 if (strcmp (name, "x11-display") == 0)
1152 const gchar *display;
1153 g_variant_get (value, "&s", &display);
1154 g_string_append_printf (cookie, "-x%s", display);
1158 session->cookie = cookie->str;
1159 g_string_free (cookie, FALSE);
1160 session->path = g_strdup_printf ("/org/freedesktop/ConsoleKit/Session%d", ck_session_index++);
1161 session->id = g_dbus_connection_register_object (connection,
1163 ck_session_info->interfaces[0],
1169 g_warning ("Failed to register CK Session: %s", error->message);
1170 g_clear_error (&error);
1176 handle_ck_call (GDBusConnection *connection,
1177 const gchar *sender,
1178 const gchar *object_path,
1179 const gchar *interface_name,
1180 const gchar *method_name,
1181 GVariant *parameters,
1182 GDBusMethodInvocation *invocation,
1185 if (strcmp (method_name, "CanRestart") == 0)
1187 check_status ("CONSOLE-KIT CAN-RESTART");
1188 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
1190 else if (strcmp (method_name, "CanStop") == 0)
1192 check_status ("CONSOLE-KIT CAN-STOP");
1193 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
1195 else if (strcmp (method_name, "CloseSession") == 0)
1196 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
1197 else if (strcmp (method_name, "OpenSession") == 0)
1199 GVariantBuilder params;
1200 g_variant_builder_init (¶ms, G_VARIANT_TYPE ("a(sv)"));
1201 CKSession *session = open_ck_session (connection, g_variant_builder_end (¶ms));
1202 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", session->cookie));
1204 else if (strcmp (method_name, "OpenSessionWithParameters") == 0)
1206 CKSession *session = open_ck_session (connection, g_variant_get_child_value (parameters, 0));
1207 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", session->cookie));
1209 else if (strcmp (method_name, "GetSessionForCookie") == 0)
1214 g_variant_get (parameters, "(&s)", &cookie);
1216 for (link = ck_sessions; link; link = link->next)
1218 CKSession *session = link->data;
1219 if (strcmp (session->cookie, cookie) == 0)
1221 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", session->path));
1226 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Unable to find session for cookie");
1228 else if (strcmp (method_name, "Restart") == 0)
1230 check_status ("CONSOLE-KIT RESTART");
1231 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1233 else if (strcmp (method_name, "Stop") == 0)
1235 check_status ("CONSOLE-KIT STOP");
1236 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1239 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1243 handle_ck_session_call (GDBusConnection *connection,
1244 const gchar *sender,
1245 const gchar *object_path,
1246 const gchar *interface_name,
1247 const gchar *method_name,
1248 GVariant *parameters,
1249 GDBusMethodInvocation *invocation,
1252 CKSession *session = user_data;
1254 if (strcmp (method_name, "Lock") == 0)
1256 if (!session->locked)
1257 check_status ("CONSOLE-KIT LOCK-SESSION");
1258 session->locked = TRUE;
1259 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1261 else if (strcmp (method_name, "Unlock") == 0)
1263 if (session->locked)
1264 check_status ("CONSOLE-KIT UNLOCK-SESSION");
1265 session->locked = FALSE;
1266 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1268 else if (strcmp (method_name, "Activate") == 0)
1270 gchar *status = g_strdup_printf ("CONSOLE-KIT ACTIVATE-SESSION SESSION=%s", session->cookie);
1271 check_status (status);
1274 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1277 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1281 ck_name_acquired_cb (GDBusConnection *connection,
1285 const gchar *ck_interface =
1287 " <interface name='org.freedesktop.ConsoleKit.Manager'>"
1288 " <method name='CanRestart'>"
1289 " <arg name='can_restart' direction='out' type='b'/>"
1291 " <method name='CanStop'>"
1292 " <arg name='can_stop' direction='out' type='b'/>"
1294 " <method name='CloseSession'>"
1295 " <arg name='cookie' direction='in' type='s'/>"
1296 " <arg name='result' direction='out' type='b'/>"
1298 " <method name='OpenSession'>"
1299 " <arg name='cookie' direction='out' type='s'/>"
1301 " <method name='OpenSessionWithParameters'>"
1302 " <arg name='parameters' direction='in' type='a(sv)'/>"
1303 " <arg name='cookie' direction='out' type='s'/>"
1305 " <method name='GetSessionForCookie'>"
1306 " <arg name='cookie' direction='in' type='s'/>"
1307 " <arg name='ssid' direction='out' type='o'/>"
1309 " <method name='Restart'/>"
1310 " <method name='Stop'/>"
1311 " <signal name='SeatAdded'>"
1312 " <arg name='seat' type='o'/>"
1314 " <signal name='SeatRemoved'>"
1315 " <arg name='seat' type='o'/>"
1319 static const GDBusInterfaceVTable ck_vtable =
1323 const gchar *ck_session_interface =
1325 " <interface name='org.freedesktop.ConsoleKit.Session'>"
1326 " <method name='Lock'/>"
1327 " <method name='Unlock'/>"
1328 " <method name='Activate'/>"
1331 GDBusNodeInfo *ck_info;
1332 GError *error = NULL;
1334 ck_info = g_dbus_node_info_new_for_xml (ck_interface, &error);
1336 g_warning ("Failed to parse D-Bus interface: %s", error->message);
1337 g_clear_error (&error);
1340 ck_session_info = g_dbus_node_info_new_for_xml (ck_session_interface, &error);
1342 g_warning ("Failed to parse D-Bus interface: %s", error->message);
1343 g_clear_error (&error);
1344 if (!ck_session_info)
1346 g_dbus_connection_register_object (connection,
1347 "/org/freedesktop/ConsoleKit/Manager",
1348 ck_info->interfaces[0],
1353 g_warning ("Failed to register console kit service: %s", error->message);
1354 g_clear_error (&error);
1355 g_dbus_node_info_unref (ck_info);
1358 if (service_count == 0)
1363 start_console_kit_daemon (void)
1366 g_bus_own_name (G_BUS_TYPE_SYSTEM,
1367 "org.freedesktop.ConsoleKit",
1368 G_BUS_NAME_OWNER_FLAGS_NONE,
1370 ck_name_acquired_cb,
1377 handle_login1_seat_call (GDBusConnection *connection,
1378 const gchar *sender,
1379 const gchar *object_path,
1380 const gchar *interface_name,
1381 const gchar *method_name,
1382 GVariant *parameters,
1383 GDBusMethodInvocation *invocation,
1386 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1390 handle_login1_seat_get_property (GDBusConnection *connection,
1391 const gchar *sender,
1392 const gchar *object_path,
1393 const gchar *interface_name,
1394 const gchar *property_name,
1398 Login1Seat *seat = user_data;
1400 if (strcmp (property_name, "CanGraphical") == 0)
1401 return g_variant_new_boolean (seat->can_graphical);
1402 else if (strcmp (property_name, "CanMultiSession") == 0)
1403 return g_variant_new_boolean (seat->can_multi_session);
1404 else if (strcmp (property_name, "Id") == 0)
1405 return g_variant_new_string (seat->id);
1411 add_login1_seat (GDBusConnection *connection, const gchar *id, gboolean can_graphical, gboolean can_multi_session, gboolean emit_signal)
1414 GError *error = NULL;
1415 GDBusNodeInfo *login1_seat_info;
1417 const gchar *login1_seat_interface =
1419 " <interface name='org.freedesktop.login1.Seat'>"
1422 static const GDBusInterfaceVTable login1_seat_vtable =
1424 handle_login1_seat_call,
1425 handle_login1_seat_get_property,
1428 seat = g_malloc0 (sizeof (Login1Seat));
1429 login1_seats = g_list_append (login1_seats, seat);
1430 seat->id = g_strdup (id);
1431 seat->path = g_strdup_printf ("/org/freedesktop/login1/seat/%s", seat->id);
1432 seat->can_graphical = can_graphical;
1433 seat->can_multi_session = can_multi_session;
1435 login1_seat_info = g_dbus_node_info_new_for_xml (login1_seat_interface, &error);
1437 g_warning ("Failed to parse login1 seat D-Bus interface: %s", error->message);
1438 g_clear_error (&error);
1439 if (!login1_seat_info)
1442 g_dbus_connection_register_object (connection,
1444 login1_seat_info->interfaces[0],
1445 &login1_seat_vtable,
1450 g_warning ("Failed to register login1 seat: %s", error->message);
1451 g_clear_error (&error);
1452 g_dbus_node_info_unref (login1_seat_info);
1456 g_dbus_connection_emit_signal (connection,
1458 "/org/freedesktop/login1",
1459 "org.freedesktop.login1.Manager",
1461 g_variant_new ("(so)", seat->id, seat->path),
1464 g_warning ("Failed to emit SeatNew: %s", error->message);
1465 g_clear_error (&error);
1472 find_seat (const gchar *id)
1477 for (link = login1_seats; link; link = link->next)
1480 if (strcmp (seat->id, id) == 0)
1488 remove_login1_seat (GDBusConnection *connection, const gchar *id)
1491 GError *error = NULL;
1493 seat = find_seat (id);
1497 g_dbus_connection_emit_signal (connection,
1499 "/org/freedesktop/login1",
1500 "org.freedesktop.login1.Manager",
1502 g_variant_new ("(so)", seat->id, seat->path),
1505 g_warning ("Failed to emit SeatNew: %s", error->message);
1506 g_clear_error (&error);
1508 login1_seats = g_list_remove (login1_seats, seat);
1510 g_free (seat->path);
1515 handle_login1_session_call (GDBusConnection *connection,
1516 const gchar *sender,
1517 const gchar *object_path,
1518 const gchar *interface_name,
1519 const gchar *method_name,
1520 GVariant *parameters,
1521 GDBusMethodInvocation *invocation,
1524 Login1Session *session = user_data;
1526 if (strcmp (method_name, "Lock") == 0)
1528 if (!session->locked)
1530 gchar *status = g_strdup_printf ("LOGIN1 LOCK-SESSION SESSION=%s", strrchr (object_path, '/') + 1);
1531 check_status (status);
1534 session->locked = TRUE;
1535 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1537 else if (strcmp (method_name, "Unlock") == 0)
1539 if (session->locked)
1541 gchar *status = g_strdup_printf ("LOGIN1 UNLOCK-SESSION SESSION=%s", strrchr (object_path, '/') + 1);
1542 check_status (status);
1545 session->locked = FALSE;
1546 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1548 else if (strcmp (method_name, "Activate") == 0)
1550 gchar *status = g_strdup_printf ("LOGIN1 ACTIVATE-SESSION SESSION=%s", strrchr (object_path, '/') + 1);
1551 check_status (status);
1554 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1557 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1560 static Login1Session *
1561 open_login1_session (GDBusConnection *connection,
1564 Login1Session *session;
1565 GError *error = NULL;
1566 GDBusNodeInfo *login1_session_info;
1568 const gchar *login1_session_interface =
1570 " <interface name='org.freedesktop.login1.Session'>"
1571 " <method name='Lock'/>"
1572 " <method name='Unlock'/>"
1573 " <method name='Activate'/>"
1576 static const GDBusInterfaceVTable login1_session_vtable =
1578 handle_login1_session_call,
1581 session = g_malloc0 (sizeof (Login1Session));
1582 login1_sessions = g_list_append (login1_sessions, session);
1584 session->path = g_strdup_printf ("/org/freedesktop/login1/Session/c%d", login1_session_index++);
1586 login1_session_info = g_dbus_node_info_new_for_xml (login1_session_interface, &error);
1588 g_warning ("Failed to parse login1 session D-Bus interface: %s", error->message);
1589 g_clear_error (&error);
1590 if (!login1_session_info)
1593 g_dbus_connection_register_object (connection,
1595 login1_session_info->interfaces[0],
1596 &login1_session_vtable,
1601 g_warning ("Failed to register login1 session: %s", error->message);
1602 g_clear_error (&error);
1603 g_dbus_node_info_unref (login1_session_info);
1609 handle_login1_call (GDBusConnection *connection,
1610 const gchar *sender,
1611 const gchar *object_path,
1612 const gchar *interface_name,
1613 const gchar *method_name,
1614 GVariant *parameters,
1615 GDBusMethodInvocation *invocation,
1618 if (strcmp (method_name, "ListSeats") == 0)
1620 GVariantBuilder seats;
1623 g_variant_builder_init (&seats, G_VARIANT_TYPE ("a(so)"));
1624 for (link = login1_seats; link; link = link->next)
1626 Login1Seat *seat = link->data;
1627 g_variant_builder_add (&seats, "(so)", seat->id, seat->path);
1629 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a(so))", g_variant_builder_end (&seats)));
1631 else if (strcmp (method_name, "GetSessionByPID") == 0)
1633 /* Look for a session with our PID, and create one if we don't have one already. */
1636 Login1Session *ret = NULL;
1638 g_variant_get (parameters, "(u)", &pid);
1640 for (link = login1_sessions; link; link = link->next)
1642 Login1Session *session;
1643 session = link->data;
1644 if (session->pid == pid)
1652 ret = open_login1_session (connection, parameters);
1654 g_dbus_method_invocation_return_value (invocation,
1655 g_variant_new("(o)", ret->path));
1658 else if (strcmp (method_name, "CanReboot") == 0)
1660 check_status ("LOGIN1 CAN-REBOOT");
1661 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1663 else if (strcmp (method_name, "Reboot") == 0)
1665 gboolean interactive;
1666 g_variant_get (parameters, "(b)", &interactive);
1667 check_status ("LOGIN1 REBOOT");
1668 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1670 else if (strcmp (method_name, "CanPowerOff") == 0)
1672 check_status ("LOGIN1 CAN-POWER-OFF");
1673 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1675 else if (strcmp (method_name, "Suspend") == 0)
1677 gboolean interactive;
1678 g_variant_get (parameters, "(b)", &interactive);
1679 check_status ("LOGIN1 SUSPEND");
1680 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1682 else if (strcmp (method_name, "CanSuspend") == 0)
1684 check_status ("LOGIN1 CAN-SUSPEND");
1685 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1687 else if (strcmp (method_name, "PowerOff") == 0)
1689 gboolean interactive;
1690 g_variant_get (parameters, "(b)", &interactive);
1691 check_status ("LOGIN1 POWER-OFF");
1692 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1694 else if (strcmp (method_name, "CanHibernate") == 0)
1696 check_status ("LOGIN1 CAN-HIBERNATE");
1697 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1699 else if (strcmp (method_name, "Hibernate") == 0)
1701 gboolean interactive;
1702 g_variant_get (parameters, "(b)", &interactive);
1703 check_status ("LOGIN1 HIBERNATE");
1704 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1707 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1711 login1_name_acquired_cb (GDBusConnection *connection,
1715 const gchar *login1_interface =
1717 " <interface name='org.freedesktop.login1.Manager'>"
1718 " <method name='ListSeats'>"
1719 " <arg name='seats' type='a(so)' direction='out'/>"
1721 " <method name='GetSessionByPID'>"
1722 " <arg name='pid' type='u' direction='in'/>"
1723 " <arg name='session' type='o' direction='out'/>"
1725 " <method name='CanReboot'>"
1726 " <arg name='result' direction='out' type='s'/>"
1728 " <method name='Reboot'>"
1729 " <arg name='interactive' direction='in' type='b'/>"
1731 " <method name='CanPowerOff'>"
1732 " <arg name='result' direction='out' type='s'/>"
1734 " <method name='PowerOff'>"
1735 " <arg name='interactive' direction='in' type='b'/>"
1737 " <method name='CanSuspend'>"
1738 " <arg name='result' direction='out' type='s'/>"
1740 " <method name='Suspend'>"
1741 " <arg name='interactive' direction='in' type='b'/>"
1743 " <method name='CanHibernate'>"
1744 " <arg name='result' direction='out' type='s'/>"
1746 " <method name='Hibernate'>"
1747 " <arg name='interactive' direction='in' type='b'/>"
1749 " <signal name='SeatNew'>"
1750 " <arg name='seat' type='so'/>"
1752 " <signal name='SeatRemoved'>"
1753 " <arg name='seat' type='so'/>"
1757 static const GDBusInterfaceVTable login1_vtable =
1761 GDBusNodeInfo *login1_info;
1762 GError *error = NULL;
1764 login1_info = g_dbus_node_info_new_for_xml (login1_interface, &error);
1766 g_warning ("Failed to parse login1 D-Bus interface: %s", error->message);
1767 g_clear_error (&error);
1770 g_dbus_connection_register_object (connection,
1771 "/org/freedesktop/login1",
1772 login1_info->interfaces[0],
1777 g_warning ("Failed to register login1 service: %s", error->message);
1778 g_clear_error (&error);
1779 g_dbus_node_info_unref (login1_info);
1781 /* We always have seat0 */
1782 add_login1_seat (connection, "seat0", TRUE, TRUE, FALSE);
1785 if (service_count == 0)
1790 start_login1_daemon (void)
1793 g_bus_own_name (G_BUS_TYPE_SYSTEM,
1794 "org.freedesktop.login1",
1795 G_BUS_NAME_OWNER_FLAGS_NONE,
1797 login1_name_acquired_cb,
1803 static AccountsUser *
1804 get_accounts_user_by_uid (guint uid)
1808 for (link = accounts_users; link; link = link->next)
1810 AccountsUser *u = link->data;
1818 static AccountsUser *
1819 get_accounts_user_by_name (const gchar *username)
1823 for (link = accounts_users; link; link = link->next)
1825 AccountsUser *u = link->data;
1826 if (strcmp (u->user_name, username) == 0)
1834 accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal)
1836 GError *error = NULL;
1838 user->hidden = hidden;
1840 if (user->hidden && user->id != 0)
1842 g_dbus_connection_unregister_object (accounts_connection, user->id);
1843 g_dbus_connection_emit_signal (accounts_connection,
1845 "/org/freedesktop/Accounts",
1846 "org.freedesktop.Accounts",
1848 g_variant_new ("(o)", user->path),
1851 g_warning ("Failed to emit UserDeleted: %s", error->message);
1852 g_clear_error (&error);
1856 if (!user->hidden && user->id == 0)
1858 user->id = g_dbus_connection_register_object (accounts_connection,
1860 user_info->interfaces[0],
1866 g_warning ("Failed to register user: %s", error->message);
1867 g_clear_error (&error);
1869 g_dbus_connection_emit_signal (accounts_connection,
1871 "/org/freedesktop/Accounts",
1872 "org.freedesktop.Accounts",
1874 g_variant_new ("(o)", user->path),
1877 g_warning ("Failed to emit UserAdded: %s", error->message);
1878 g_clear_error (&error);
1883 load_passwd_file (void)
1885 gchar *path, *data, **lines;
1886 gchar **user_filter = NULL;
1889 if (g_key_file_has_key (config, "test-runner-config", "accounts-service-user-filter", NULL))
1893 filter = g_key_file_get_string (config, "test-runner-config", "accounts-service-user-filter", NULL);
1894 user_filter = g_strsplit (filter, " ", -1);
1898 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
1899 g_file_get_contents (path, &data, NULL, NULL);
1901 lines = g_strsplit (data, "\n", -1);
1904 for (i = 0; lines[i]; i++)
1908 gchar *user_name, *real_name;
1909 AccountsUser *user = NULL;
1911 fields = g_strsplit (lines[i], ":", -1);
1912 if (fields == NULL || g_strv_length (fields) < 7)
1914 g_strfreev (fields);
1918 user_name = fields[0];
1919 uid = atoi (fields[2]);
1920 real_name = fields[4];
1922 user = get_accounts_user_by_uid (uid);
1926 GKeyFile *dmrc_file;
1928 user = g_malloc0 (sizeof (AccountsUser));
1929 accounts_users = g_list_append (accounts_users, user);
1931 /* Only allow users in whitelist */
1932 user->hidden = FALSE;
1937 user->hidden = TRUE;
1938 for (j = 0; user_filter[j] != NULL; j++)
1939 if (strcmp (user_name, user_filter[j]) == 0)
1940 user->hidden = FALSE;
1943 dmrc_file = g_key_file_new ();
1944 path = g_build_filename (temp_dir, "home", user_name, ".dmrc", NULL);
1945 g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
1949 user->user_name = g_strdup (user_name);
1950 user->real_name = g_strdup (real_name);
1951 user->home_directory = g_build_filename (temp_dir, "home", user_name, NULL);
1952 user->language = g_key_file_get_string (dmrc_file, "Desktop", "Language", NULL);
1953 /* DMRC contains a locale, strip the codeset off it to get the language */
1956 gchar *c = strchr (user->language, '.');
1960 user->xsession = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL);
1961 user->layouts = g_key_file_get_string_list (dmrc_file, "X-Accounts", "Layouts", NULL, NULL);
1964 user->layouts = g_malloc (sizeof (gchar *) * 2);
1965 user->layouts[0] = g_key_file_get_string (dmrc_file, "Desktop", "Layout", NULL);
1966 user->layouts[1] = NULL;
1968 user->has_messages = g_key_file_get_boolean (dmrc_file, "X-Accounts", "HasMessages", NULL);
1969 user->path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", uid);
1970 accounts_user_set_hidden (user, user->hidden, FALSE);
1972 g_key_file_free (dmrc_file);
1975 g_strfreev (fields);
1982 handle_accounts_call (GDBusConnection *connection,
1983 const gchar *sender,
1984 const gchar *object_path,
1985 const gchar *interface_name,
1986 const gchar *method_name,
1987 GVariant *parameters,
1988 GDBusMethodInvocation *invocation,
1991 if (strcmp (method_name, "ListCachedUsers") == 0)
1993 GVariantBuilder builder;
1996 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
1998 load_passwd_file ();
1999 for (link = accounts_users; link; link = link->next)
2001 AccountsUser *user = link->data;
2002 if (!user->hidden && user->uid >= 1000)
2003 g_variant_builder_add_value (&builder, g_variant_new_object_path (user->path));
2006 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ao)", &builder));
2008 else if (strcmp (method_name, "FindUserByName") == 0)
2010 AccountsUser *user = NULL;
2013 g_variant_get (parameters, "(&s)", &user_name);
2015 load_passwd_file ();
2016 user = get_accounts_user_by_name (user_name);
2020 accounts_user_set_hidden (user, FALSE, TRUE);
2021 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", user->path));
2024 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such user: %s", user_name);
2027 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
2031 handle_user_call (GDBusConnection *connection,
2032 const gchar *sender,
2033 const gchar *object_path,
2034 const gchar *interface_name,
2035 const gchar *method_name,
2036 GVariant *parameters,
2037 GDBusMethodInvocation *invocation,
2040 AccountsUser *user = user_data;
2042 if (strcmp (method_name, "SetXSession") == 0)
2046 g_variant_get (parameters, "(&s)", &xsession);
2048 g_free (user->xsession);
2049 user->xsession = g_strdup (xsession);
2051 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
2053 /* And notify others that it took */
2054 g_dbus_connection_emit_signal (accounts_connection,
2057 "org.freedesktop.Accounts.User",
2059 g_variant_new ("()"),
2063 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
2067 handle_user_get_property (GDBusConnection *connection,
2068 const gchar *sender,
2069 const gchar *object_path,
2070 const gchar *interface_name,
2071 const gchar *property_name,
2075 AccountsUser *user = user_data;
2077 if (strcmp (property_name, "UserName") == 0)
2078 return g_variant_new_string (user->user_name);
2079 else if (strcmp (property_name, "RealName") == 0)
2080 return g_variant_new_string (user->real_name);
2081 else if (strcmp (property_name, "HomeDirectory") == 0)
2082 return g_variant_new_string (user->home_directory);
2083 else if (strcmp (property_name, "SystemAccount") == 0)
2084 return g_variant_new_boolean (user->uid < 1000);
2085 else if (strcmp (property_name, "BackgroundFile") == 0)
2086 return g_variant_new_string (user->background ? user->background : "");
2087 else if (strcmp (property_name, "Language") == 0)
2088 return g_variant_new_string (user->language ? user->language : "");
2089 else if (strcmp (property_name, "IconFile") == 0)
2090 return g_variant_new_string (user->image ? user->image : "");
2091 else if (strcmp (property_name, "Shell") == 0)
2092 return g_variant_new_string ("/bin/sh");
2093 else if (strcmp (property_name, "Uid") == 0)
2094 return g_variant_new_uint64 (user->uid);
2095 else if (strcmp (property_name, "XSession") == 0)
2096 return g_variant_new_string (user->xsession ? user->xsession : "");
2097 else if (strcmp (property_name, "XKeyboardLayouts") == 0)
2099 if (user->layouts != NULL)
2100 return g_variant_new_strv ((const gchar * const *) user->layouts, -1);
2102 return g_variant_new_strv (NULL, 0);
2104 else if (strcmp (property_name, "XHasMessages") == 0)
2105 return g_variant_new_boolean (user->has_messages);
2111 accounts_name_acquired_cb (GDBusConnection *connection,
2115 const gchar *accounts_interface =
2117 " <interface name='org.freedesktop.Accounts'>"
2118 " <method name='ListCachedUsers'>"
2119 " <arg name='user' direction='out' type='ao'/>"
2121 " <method name='FindUserByName'>"
2122 " <arg name='name' direction='in' type='s'/>"
2123 " <arg name='user' direction='out' type='o'/>"
2125 " <signal name='UserAdded'>"
2126 " <arg name='user' type='o'/>"
2128 " <signal name='UserDeleted'>"
2129 " <arg name='user' type='o'/>"
2133 static const GDBusInterfaceVTable accounts_vtable =
2135 handle_accounts_call,
2137 const gchar *user_interface =
2139 " <interface name='org.freedesktop.Accounts.User'>"
2140 " <method name='SetXSession'>"
2141 " <arg name='x_session' direction='in' type='s'/>"
2143 " <property name='UserName' type='s' access='read'/>"
2144 " <property name='RealName' type='s' access='read'/>"
2145 " <property name='HomeDirectory' type='s' access='read'/>"
2146 " <property name='SystemAccount' type='b' access='read'/>"
2147 " <property name='BackgroundFile' type='s' access='read'/>"
2148 " <property name='Language' type='s' access='read'/>"
2149 " <property name='IconFile' type='s' access='read'/>"
2150 " <property name='Shell' type='s' access='read'/>"
2151 " <property name='Uid' type='t' access='read'/>"
2152 " <property name='XSession' type='s' access='read'/>"
2153 " <property name='XKeyboardLayouts' type='as' access='read'/>"
2154 " <property name='XHasMessages' type='b' access='read'/>"
2155 " <signal name='Changed' />"
2158 GError *error = NULL;
2160 accounts_connection = connection;
2162 accounts_info = g_dbus_node_info_new_for_xml (accounts_interface, &error);
2164 g_warning ("Failed to parse D-Bus interface: %s", error->message);
2165 g_clear_error (&error);
2168 user_info = g_dbus_node_info_new_for_xml (user_interface, &error);
2170 g_warning ("Failed to parse D-Bus interface: %s", error->message);
2171 g_clear_error (&error);
2174 g_dbus_connection_register_object (connection,
2175 "/org/freedesktop/Accounts",
2176 accounts_info->interfaces[0],
2182 g_warning ("Failed to register accounts service: %s", error->message);
2183 g_clear_error (&error);
2184 g_dbus_node_info_unref (accounts_info);
2187 if (service_count == 0)
2192 start_accounts_service_daemon (void)
2195 g_bus_own_name (G_BUS_TYPE_SYSTEM,
2196 "org.freedesktop.Accounts",
2197 G_BUS_NAME_OWNER_FLAGS_NONE,
2198 accounts_name_acquired_cb,
2212 signal_cb (gpointer user_data)
2214 g_print ("Caught signal, quitting\n");
2215 quit (EXIT_FAILURE);
2220 properties_changed_cb (GDBusConnection *connection,
2221 const gchar *sender_name,
2222 const gchar *object_path,
2223 const gchar *interface_name,
2224 const gchar *signal_name,
2225 GVariant *parameters,
2228 const gchar *interface, *name;
2231 GVariantIter *changed_properties, *invalidated_properties;
2234 g_variant_get (parameters, "(&sa{sv}as)", &interface, &changed_properties, &invalidated_properties);
2236 status = g_string_new ("RUNNER DBUS-PROPERTIES-CHANGED");
2237 g_string_append_printf (status, " PATH=%s", object_path);
2238 g_string_append_printf (status, " INTERFACE=%s", interface);
2239 for (i = 0; g_variant_iter_loop (changed_properties, "{&sv}", &name, &value); i++)
2242 g_string_append (status, " CHANGED=");
2244 g_string_append (status, ",");
2245 g_string_append (status, name);
2246 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("ao")))
2251 g_variant_iter_init (&iter, value);
2252 while (g_variant_iter_loop (&iter, "&o", &path))
2253 g_string_append_printf (status, ":%s", path);
2256 for (i = 0; g_variant_iter_loop (invalidated_properties, "&s", &name); i++)
2259 g_string_append (status, " INVALIDATED=");
2261 g_string_append (status, ",");
2262 g_string_append (status, name);
2265 check_status (status->str);
2266 g_string_free (status, TRUE);
2270 dbus_signal_cb (GDBusConnection *connection,
2271 const gchar *sender_name,
2272 const gchar *object_path,
2273 const gchar *interface_name,
2274 const gchar *signal_name,
2275 GVariant *parameters,
2280 status = g_string_new ("RUNNER DBUS-SIGNAL");
2281 g_string_append_printf (status, " PATH=%s", object_path);
2282 g_string_append_printf (status, " INTERFACE=%s", interface_name);
2283 g_string_append_printf (status, " NAME=%s", signal_name);
2285 check_status (status->str);
2286 g_string_free (status, TRUE);
2290 main (int argc, char **argv)
2294 gchar *greeter = NULL, *script_name, *config_file, *additional_system_config;
2295 gchar *additional_config, *path, *path1, *path2, *ld_preload, *ld_library_path, *home_dir;
2296 GString *passwd_data, *group_data;
2297 GSource *status_source;
2299 GError *error = NULL;
2301 #if !defined(GLIB_VERSION_2_36)
2305 loop = g_main_loop_new (NULL, FALSE);
2307 g_unix_signal_add (SIGINT, signal_cb, NULL);
2308 g_unix_signal_add (SIGTERM, signal_cb, NULL);
2310 children = g_hash_table_new (g_direct_hash, g_direct_equal);
2314 g_printerr ("Usage %s SCRIPT-NAME GREETER\n", argv[0]);
2315 quit (EXIT_FAILURE);
2317 script_name = argv[1];
2318 config_file = g_strdup_printf ("%s.conf", script_name);
2319 config_path = g_build_filename (SRCDIR, "tests", "scripts", config_file, NULL);
2320 g_free (config_file);
2322 config = g_key_file_new ();
2323 g_key_file_load_from_file (config, config_path, G_KEY_FILE_NONE, NULL);
2325 load_script (config_path);
2327 if (!getcwd (cwd, 1024))
2329 g_critical ("Error getting current directory: %s", strerror (errno));
2330 quit (EXIT_FAILURE);
2333 /* Don't contact our X server */
2334 g_unsetenv ("DISPLAY");
2336 /* Don't let XDG vars from system affect tests */
2337 g_unsetenv ("XDG_CONFIG_DIRS");
2338 g_unsetenv ("XDG_DATA_DIRS");
2340 /* Override system calls */
2341 ld_preload = g_build_filename (BUILDDIR, "tests", "src", ".libs", "libsystem.so", NULL);
2342 g_setenv ("LD_PRELOAD", ld_preload, TRUE);
2343 g_free (ld_preload);
2345 /* Run test programs */
2346 path = g_strdup_printf ("%s/tests/src/.libs:%s/tests/src:%s/tests/src:%s/src:%s", BUILDDIR, BUILDDIR, SRCDIR, BUILDDIR, g_getenv ("PATH"));
2347 g_setenv ("PATH", path, TRUE);
2350 /* Use locally built libraries */
2351 path1 = g_build_filename (BUILDDIR, "liblightdm-gobject", ".libs", NULL);
2352 path2 = g_build_filename (BUILDDIR, "liblightdm-qt", ".libs", NULL);
2353 ld_library_path = g_strdup_printf ("%s:%s", path1, path2);
2356 g_setenv ("LD_LIBRARY_PATH", ld_library_path, TRUE);
2357 g_free (ld_library_path);
2358 path1 = g_build_filename (BUILDDIR, "liblightdm-gobject", NULL);
2359 g_setenv ("GI_TYPELIB_PATH", path1, TRUE);
2362 /* Run in a temporary directory inside the build directory */
2363 /* Note we have to pick a name that is short since Unix sockets in this directory have a 108 character limit on their paths */
2368 name = g_strdup_printf (".r%d", i);
2370 temp_dir = g_build_filename ("/tmp", name, NULL);
2372 if (!g_file_test (temp_dir, G_FILE_TEST_EXISTS))
2376 g_mkdir_with_parents (temp_dir, 0755);
2377 g_setenv ("LIGHTDM_TEST_ROOT", temp_dir, TRUE);
2379 /* Open socket for status */
2380 /* Note we have to pick a socket name that is short since there is a 108 character limit on the name */
2381 status_socket_name = g_build_filename (temp_dir, ".s", NULL);
2382 unlink (status_socket_name);
2383 status_socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
2385 g_warning ("Error creating status socket %s: %s", status_socket_name, error->message);
2386 g_clear_error (&error);
2389 GSocketAddress *address;
2392 address = g_unix_socket_address_new (status_socket_name);
2393 result = g_socket_bind (status_socket, address, FALSE, &error);
2394 g_object_unref (address);
2396 g_warning ("Error binding status socket %s: %s", status_socket_name, error->message);
2397 g_clear_error (&error);
2400 result = g_socket_listen (status_socket, &error);
2402 g_warning ("Error listening on status socket %s: %s", status_socket_name, error->message);
2403 g_clear_error (&error);
2407 g_object_unref (status_socket);
2408 status_socket = NULL;
2412 quit (EXIT_FAILURE);
2413 status_source = g_socket_create_source (status_socket, G_IO_IN, NULL);
2414 g_source_set_callback (status_source, status_connect_cb, NULL, NULL);
2415 g_source_attach (status_source, NULL);
2417 /* Set up a skeleton file system */
2418 g_mkdir_with_parents (g_strdup_printf ("%s/etc", temp_dir), 0755);
2419 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share", temp_dir), 0755);
2420 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/sessions", temp_dir), 0755);
2421 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/remote-sessions", temp_dir), 0755);
2422 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/greeters", temp_dir), 0755);
2423 g_mkdir_with_parents (g_strdup_printf ("%s/tmp", temp_dir), 0755);
2424 g_mkdir_with_parents (g_strdup_printf ("%s/var/lib/lightdm-data", temp_dir), 0755);
2425 g_mkdir_with_parents (g_strdup_printf ("%s/var/run", temp_dir), 0755);
2426 g_mkdir_with_parents (g_strdup_printf ("%s/var/log", temp_dir), 0755);
2428 /* Copy over the configuration */
2429 g_mkdir_with_parents (g_strdup_printf ("%s/etc/lightdm", temp_dir), 0755);
2430 if (!g_key_file_has_key (config, "test-runner-config", "have-config", NULL) || g_key_file_get_boolean (config, "test-runner-config", "have-config", NULL))
2431 if (system (g_strdup_printf ("cp %s %s/etc/lightdm/lightdm.conf", config_path, temp_dir)))
2432 perror ("Failed to copy configuration");
2434 additional_system_config = g_key_file_get_string (config, "test-runner-config", "additional-system-config", NULL);
2435 if (additional_system_config)
2439 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/lightdm.conf.d", temp_dir), 0755);
2441 files = g_strsplit (additional_system_config, " ", -1);
2442 for (i = 0; files[i]; i++)
2443 if (system (g_strdup_printf ("cp %s/tests/scripts/%s %s/usr/share/lightdm/lightdm.conf.d", SRCDIR, files[i], temp_dir)))
2444 perror ("Failed to copy configuration");
2448 additional_config = g_key_file_get_string (config, "test-runner-config", "additional-config", NULL);
2449 if (additional_config)
2453 g_mkdir_with_parents (g_strdup_printf ("%s/etc/xdg/lightdm/lightdm.conf.d", temp_dir), 0755);
2455 files = g_strsplit (additional_config, " ", -1);
2456 for (i = 0; files[i]; i++)
2457 if (system (g_strdup_printf ("cp %s/tests/scripts/%s %s/etc/xdg/lightdm/lightdm.conf.d", SRCDIR, files[i], temp_dir)))
2458 perror ("Failed to copy configuration");
2462 if (g_key_file_has_key (config, "test-runner-config", "shared-data-dirs", NULL))
2468 dir_string = g_key_file_get_string (config, "test-runner-config", "shared-data-dirs", NULL);
2469 dirs = g_strsplit (dir_string, " ", -1);
2470 g_free (dir_string);
2472 for (i = 0; dirs[i]; i++)
2474 gchar **fields = g_strsplit (dirs[i], ":", -1);
2475 if (g_strv_length (fields) == 4)
2477 gchar *path = g_strdup_printf ("%s/var/lib/lightdm-data/%s", temp_dir, fields[0]);
2478 int uid = g_ascii_strtoll (fields[1], NULL, 10);
2479 int gid = g_ascii_strtoll (fields[2], NULL, 10);
2480 int mode = g_ascii_strtoll (fields[3], NULL, 8);
2481 g_mkdir (path, mode);
2482 g_chmod (path, mode); /* mkdir filters by umask, so make sure we have what we want */
2483 if (chown (path, uid, gid) < 0)
2484 g_warning ("chown (%s) failed: %s", path, strerror (errno));
2487 g_strfreev (fields);
2493 /* Always copy the script */
2494 if (system (g_strdup_printf ("cp %s %s/script", config_path, temp_dir)))
2495 perror ("Failed to copy configuration");
2497 /* Copy over the greeter files */
2498 if (system (g_strdup_printf ("cp %s/sessions/* %s/usr/share/lightdm/sessions", DATADIR, temp_dir)))
2499 perror ("Failed to copy sessions");
2500 if (system (g_strdup_printf ("cp %s/remote-sessions/* %s/usr/share/lightdm/remote-sessions", DATADIR, temp_dir)))
2501 perror ("Failed to copy remote sessions");
2502 if (system (g_strdup_printf ("cp %s/greeters/* %s/usr/share/lightdm/greeters", DATADIR, temp_dir)))
2503 perror ("Failed to copy greeters");
2505 /* Set up the default greeter */
2506 path = g_build_filename (temp_dir, "usr", "share", "lightdm", "greeters", "default.desktop", NULL);
2507 greeter = g_strdup_printf ("%s.desktop", argv[2]);
2508 if (symlink (greeter, path) < 0)
2510 g_printerr ("Failed to make greeter symlink %s->%s: %s\n", path, greeter, strerror (errno));
2511 quit (EXIT_FAILURE);
2516 home_dir = g_build_filename (temp_dir, "home", NULL);
2518 /* Make fake users */
2528 {"root", "", "root", 0},
2529 /* Unprivileged account for greeters */
2530 {"lightdm", "", "", 100},
2531 /* These accounts have a password */
2532 {"have-password1", "password", "Password User 1", 1000},
2533 {"have-password2", "password", "Password User 2", 1001},
2534 {"have-password3", "password", "Password User 3", 1002},
2535 {"have-password4", "password", "Password User 4", 1003},
2536 /* This account always prompts for a password, even if using the lightdm-autologin service */
2537 {"always-password", "password", "Password User 4", 1004},
2538 /* These accounts have no password */
2539 {"no-password1", "", "No Password User 1", 1005},
2540 {"no-password2", "", "No Password User 2", 1006},
2541 {"no-password3", "", "No Password User 3", 1007},
2542 {"no-password4", "", "No Password User 4", 1008},
2543 /* This account has a keyboard layout */
2544 {"have-layout", "", "Layout User", 1009},
2545 /* This account has a set of keyboard layouts */
2546 {"have-layouts", "", "Layouts User", 1010},
2547 /* This account has a language set */
2548 {"have-language", "", "Language User", 1011},
2549 /* This account has a preconfigured session */
2550 {"have-session", "", "Session User", 1012},
2551 /* This account has the home directory mounted on login */
2552 {"mount-home-dir", "", "Mounted Home Dir User", 1013},
2553 /* This account is denied access */
2554 {"denied", "", "Denied User", 1014},
2555 /* This account has expired */
2556 {"expired", "", "Expired User", 1015},
2557 /* This account needs a password change */
2558 {"new-authtok", "", "New Token User", 1016},
2559 /* This account is switched to change-user2 when authentication succeeds */
2560 {"change-user1", "", "Change User 1", 1017},
2561 {"change-user2", "", "Change User 2", 1018},
2562 /* This account switches to invalid-user when authentication succeeds */
2563 {"change-user-invalid", "", "Invalid Change User", 1019},
2564 /* This account crashes on authentication */
2565 {"crash-authenticate", "", "Crash Auth User", 1020},
2566 /* This account shows an informational prompt on login */
2567 {"info-prompt", "password", "Info Prompt", 1021},
2568 /* This account shows multiple informational prompts on login */
2569 {"multi-info-prompt","password", "Multi Info Prompt", 1022},
2570 /* This account uses two factor authentication */
2571 {"two-factor", "password", "Two Factor", 1023},
2572 /* This account has a special group */
2573 {"group-member", "password", "Group Member", 1024},
2574 /* This account has the home directory created when the session starts */
2575 {"make-home-dir", "", "Make Home Dir User", 1025},
2576 /* This account fails to open a session */
2577 {"session-error", "password", "Session Error", 1026},
2578 /* This account can't establish credentials */
2579 {"cred-error", "password", "Cred Error", 1027},
2580 /* This account has expired credentials */
2581 {"cred-expired", "password", "Cred Expired", 1028},
2582 /* This account has cannot access their credentials */
2583 {"cred-unavail", "password", "Cred Unavail", 1029},
2584 /* This account sends informational messages for each PAM function that is called */
2585 {"log-pam", "password", "Log PAM", 1030},
2586 /* This account shows multiple prompts on login */
2587 {"multi-prompt", "password", "Multi Prompt", 1031},
2588 /* This account has an existing corrupt X authority */
2589 {"corrupt-xauth", "password", "Corrupt Xauthority", 1032},
2590 /* User to test properties */
2591 {"prop-user", "", "TEST", 1033},
2592 {NULL, NULL, NULL, 0}
2594 passwd_data = g_string_new ("");
2595 group_data = g_string_new ("");
2596 for (i = 0; users[i].user_name; i++)
2598 GKeyFile *dmrc_file;
2599 gboolean save_dmrc = FALSE;
2601 if (strcmp (users[i].user_name, "mount-home-dir") != 0 && strcmp (users[i].user_name, "make-home-dir") != 0)
2603 path = g_build_filename (home_dir, users[i].user_name, NULL);
2604 g_mkdir_with_parents (path, 0755);
2605 if (chown (path, users[i].uid, users[i].uid) < 0)
2606 g_debug ("chown (%s) failed: %s", path, strerror (errno));
2610 dmrc_file = g_key_file_new ();
2611 if (strcmp (users[i].user_name, "have-session") == 0)
2613 g_key_file_set_string (dmrc_file, "Desktop", "Session", "alternative");
2616 if (strcmp (users[i].user_name, "have-layout") == 0)
2618 g_key_file_set_string (dmrc_file, "Desktop", "Layout", "us");
2621 if (strcmp (users[i].user_name, "have-layouts") == 0)
2623 g_key_file_set_string (dmrc_file, "Desktop", "Layout", "ru");
2624 g_key_file_set_string (dmrc_file, "X-Accounts", "Layouts", "fr\toss;ru;");
2627 if (strcmp (users[i].user_name, "have-language") == 0)
2629 g_key_file_set_string (dmrc_file, "Desktop", "Language", "en_AU.utf8");
2637 path = g_build_filename (home_dir, users[i].user_name, ".dmrc", NULL);
2638 data = g_key_file_to_data (dmrc_file, NULL, NULL);
2639 g_file_set_contents (path, data, -1, NULL);
2644 g_key_file_free (dmrc_file);
2646 /* Write corrupt X authority file */
2647 if (strcmp (users[i].user_name, "corrupt-xauth") == 0)
2649 gchar data[1] = { 0xFF };
2651 path = g_build_filename (home_dir, users[i].user_name, ".Xauthority", NULL);
2652 g_file_set_contents (path, data, 1, NULL);
2653 chmod (path, S_IRUSR | S_IWUSR);
2657 /* Add passwd file entry */
2658 g_string_append_printf (passwd_data, "%s:%s:%d:%d:%s:%s/home/%s:/bin/sh\n", users[i].user_name, users[i].password, users[i].uid, users[i].uid, users[i].real_name, temp_dir, users[i].user_name);
2660 /* Add group file entry */
2661 g_string_append_printf (group_data, "%s:x:%d:%s\n", users[i].user_name, users[i].uid, users[i].user_name);
2663 path = g_build_filename (temp_dir, "etc", "passwd", NULL);
2664 g_file_set_contents (path, passwd_data->str, -1, NULL);
2666 g_string_free (passwd_data, TRUE);
2668 /* Add an extra test group */
2669 g_string_append_printf (group_data, "test-group:x:111:\n");
2671 path = g_build_filename (temp_dir, "etc", "group", NULL);
2672 g_file_set_contents (path, group_data->str, -1, NULL);
2674 g_string_free (group_data, TRUE);
2676 if (g_key_file_has_key (config, "test-runner-config", "timeout", NULL))
2677 status_timeout_ms = g_key_file_get_integer (config, "test-runner-config", "timeout", NULL) * 1000;
2679 /* Start D-Bus services */
2680 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-upower", NULL))
2681 start_upower_daemon ();
2682 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-console-kit", NULL))
2683 start_console_kit_daemon ();
2684 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-login1", NULL))
2685 start_login1_daemon ();
2686 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-accounts-service", NULL))
2687 start_accounts_service_daemon ();
2689 /* Listen for daemon bus events */
2690 if (g_key_file_get_boolean (config, "test-runner-config", "log-dbus", NULL))
2692 g_dbus_connection_signal_subscribe (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
2693 "org.freedesktop.DisplayManager",
2694 "org.freedesktop.DBus.Properties",
2695 "PropertiesChanged",
2698 G_DBUS_SIGNAL_FLAGS_NONE,
2699 properties_changed_cb,
2702 g_dbus_connection_signal_subscribe (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
2703 "org.freedesktop.DisplayManager",
2704 "org.freedesktop.DisplayManager",
2708 G_DBUS_SIGNAL_FLAGS_NONE,
2714 g_main_loop_run (loop);
2716 return EXIT_FAILURE;