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 static GList *accounts_users = NULL;
61 static void handle_user_call (GDBusConnection *connection,
63 const gchar *object_path,
64 const gchar *interface_name,
65 const gchar *method_name,
67 GDBusMethodInvocation *invocation,
69 static GVariant *handle_user_get_property (GDBusConnection *connection,
71 const gchar *object_path,
72 const gchar *interface_name,
73 const gchar *property_name,
76 static const GDBusInterfaceVTable user_vtable =
79 handle_user_get_property,
81 static GDBusConnection *ck_connection = NULL;
82 static GDBusNodeInfo *ck_session_info;
89 static GList *ck_sessions = NULL;
90 static gint ck_session_index = 0;
91 static void handle_session_call (GDBusConnection *connection,
93 const gchar *object_path,
94 const gchar *interface_name,
95 const gchar *method_name,
97 GDBusMethodInvocation *invocation,
99 static const GDBusInterfaceVTable ck_session_vtable =
110 static GList *login1_sessions = NULL;
111 static gint login1_session_index = 0;
118 static GList *status_clients = NULL;
120 static void run_lightdm (void);
121 static void quit (int status);
122 static void check_status (const gchar *status);
123 static AccountsUser *get_accounts_user_by_uid (guint uid);
124 static AccountsUser *get_accounts_user_by_name (const gchar *username);
125 static void accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal);
128 kill_timeout_cb (gpointer data)
130 Process *process = data;
132 if (getenv ("DEBUG"))
133 g_print ("Sending SIGKILL to process %d\n", process->pid);
134 kill (process->pid, SIGKILL);
139 stop_process (Process *process)
141 if (process->kill_timeout != 0)
144 if (getenv ("DEBUG"))
145 g_print ("Sending SIGTERM to process %d\n", process->pid);
146 kill (process->pid, SIGTERM);
147 process->kill_timeout = g_timeout_add (KILL_TIMEOUT, kill_timeout_cb, process);
151 process_exit_cb (GPid pid, gint status, gpointer data)
156 if (getenv ("DEBUG"))
158 if (WIFEXITED (status))
159 g_print ("Process %d exited with status %d\n", pid, WEXITSTATUS (status));
161 g_print ("Process %d terminated with signal %d\n", pid, WTERMSIG (status));
164 if (lightdm_process && pid == lightdm_process->pid)
166 process = lightdm_process;
167 lightdm_process = NULL;
168 if (WIFEXITED (status))
169 status_text = g_strdup_printf ("RUNNER DAEMON-EXIT STATUS=%d", WEXITSTATUS (status));
171 status_text = g_strdup_printf ("RUNNER DAEMON-TERMINATE SIGNAL=%d", WTERMSIG (status));
172 check_status (status_text);
176 process = g_hash_table_lookup (children, GINT_TO_POINTER (pid));
179 g_hash_table_remove (children, GINT_TO_POINTER (pid));
182 if (process->kill_timeout)
183 g_source_remove (process->kill_timeout);
184 process->kill_timeout = 0;
186 /* Quit once all children have stopped */
192 watch_process (pid_t pid)
196 process = g_malloc0 (sizeof (Process));
198 process->kill_timeout = 0;
200 if (getenv ("DEBUG"))
201 g_print ("Watching process %d\n", process->pid);
202 g_child_watch_add (process->pid, process_exit_cb, NULL);
213 exit_status = status;
216 /* Stop all the children */
217 g_hash_table_iter_init (&iter, children);
222 if (!g_hash_table_iter_next (&iter, &key, &value))
225 stop_process ((Process *)value);
228 /* Don't quit until all children are stopped */
229 if (g_hash_table_size (children) > 0)
232 /* Stop the daemon */
235 stop_process (lightdm_process);
239 if (status_socket_name)
240 unlink (status_socket_name);
242 if (temp_dir && getenv ("DEBUG") == NULL)
244 gchar *command = g_strdup_printf ("rm -rf %s", temp_dir);
245 if (system (command))
246 perror ("Failed to delete temp directory");
253 fail (const gchar *event, const gchar *expected)
260 g_printerr ("Command line: %s", test_runner_command);
261 g_printerr ("Events:\n");
262 for (link = statuses; link; link = link->next)
263 g_printerr (" %s\n", (gchar *)link->data);
265 g_printerr (" %s\n", event);
267 g_printerr (" ^^^ expected \"%s\"\n", expected);
269 g_printerr ("^^^ expected nothing\n");
275 get_prefix (const gchar *text)
280 prefix = g_strdup (text);
281 for (i = 0; prefix[i] != '\0' && prefix[i] != ' '; i++);
288 get_script_line (const gchar *prefix)
292 for (link = script; link; link = link->next)
294 ScriptLine *line = link->data;
296 /* Ignore lines with other prefixes */
302 p = get_prefix (line->text);
303 matches = strcmp (prefix, p) == 0;
318 handle_command (const gchar *command)
325 while (*c && !isspace (*c))
327 name = g_strdup_printf ("%.*s", (int) (c - command), command);
329 params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
333 gchar *param_name, *param_value;
338 while (*c && !isspace (*c) && *c != '=')
343 param_name = g_strdup_printf ("%.*s", (int) (c - start), start);
352 gboolean escaped = FALSE;
356 value = g_string_new ("");
363 g_string_append_c (value, '\\');
369 else if (!escaped && *c == '\"')
372 g_string_append_c (value, *c);
375 param_value = value->str;
376 g_string_free (value, FALSE);
383 while (*c && !isspace (*c))
385 param_value = g_strdup_printf ("%.*s", (int) (c - start), start);
389 param_value = g_strdup ("");
391 g_hash_table_insert (params, param_name, param_value);
394 if (strcmp (name, "WAIT") == 0)
398 else if (strcmp (name, "LIST-SEATS") == 0)
400 GVariant *result, *value;
406 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
407 "org.freedesktop.DisplayManager",
408 "/org/freedesktop/DisplayManager",
409 "org.freedesktop.DBus.Properties",
411 g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Seats"),
412 G_VARIANT_TYPE ("(v)"),
413 G_DBUS_CALL_FLAGS_NONE,
418 status = g_string_new ("RUNNER LIST-SEATS SEATS=");
419 g_variant_get (result, "(v)", &value);
420 g_variant_get (value, "ao", &iter);
421 while (g_variant_iter_loop (iter, "&o", &path))
424 g_string_append (status, ",");
425 g_string_append (status, path);
428 g_variant_unref (value);
429 g_variant_unref (result);
431 check_status (status->str);
432 g_string_free (status, TRUE);
434 else if (strcmp (name, "LIST-SESSIONS") == 0)
436 GVariant *result, *value;
442 result = g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
443 "org.freedesktop.DisplayManager",
444 "/org/freedesktop/DisplayManager",
445 "org.freedesktop.DBus.Properties",
447 g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"),
448 G_VARIANT_TYPE ("(v)"),
449 G_DBUS_CALL_FLAGS_NONE,
454 status = g_string_new ("RUNNER LIST-SESSIONS SESSIONS=");
455 g_variant_get (result, "(v)", &value);
456 g_variant_get (value, "ao", &iter);
457 while (g_variant_iter_loop (iter, "&o", &path))
460 g_string_append (status, ",");
461 g_string_append (status, path);
464 g_variant_unref (value);
465 g_variant_unref (result);
467 check_status (status->str);
468 g_string_free (status, TRUE);
470 else if (strcmp (name, "SWITCH-TO-GREETER") == 0)
472 g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
473 "org.freedesktop.DisplayManager",
474 "/org/freedesktop/DisplayManager/Seat0",
475 "org.freedesktop.DisplayManager.Seat",
477 g_variant_new ("()"),
478 G_VARIANT_TYPE ("()"),
479 G_DBUS_CALL_FLAGS_NONE,
483 check_status ("RUNNER SWITCH-TO-GREETER");
485 else if (strcmp (name, "SWITCH-TO-USER") == 0)
487 gchar *status_text, *username;
489 username = g_hash_table_lookup (params, "USERNAME");
490 g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
491 "org.freedesktop.DisplayManager",
492 "/org/freedesktop/DisplayManager/Seat0",
493 "org.freedesktop.DisplayManager.Seat",
495 g_variant_new ("(ss)", username, ""),
496 G_VARIANT_TYPE ("()"),
497 G_DBUS_CALL_FLAGS_NONE,
501 status_text = g_strdup_printf ("RUNNER SWITCH-TO-USER USERNAME=%s", username);
502 check_status (status_text);
503 g_free (status_text);
505 else if (strcmp (name, "SWITCH-TO-GUEST") == 0)
507 g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL),
508 "org.freedesktop.DisplayManager",
509 "/org/freedesktop/DisplayManager/Seat0",
510 "org.freedesktop.DisplayManager.Seat",
512 g_variant_new ("(s)", ""),
513 G_VARIANT_TYPE ("()"),
514 G_DBUS_CALL_FLAGS_NONE,
518 check_status ("RUNNER SWITCH-TO-GUEST");
520 else if (strcmp (name, "STOP-DAEMON") == 0)
521 stop_process (lightdm_process);
522 // FIXME: Make generic RUN-COMMAND
523 else if (strcmp (name, "START-XSERVER") == 0)
525 gchar *xserver_args, *command_line;
529 GError *error = NULL;
531 xserver_args = g_hash_table_lookup (params, "ARGS");
534 command_line = g_strdup_printf ("%s/tests/src/X %s", BUILDDIR, xserver_args);
536 if (!g_shell_parse_argv (command_line, NULL, &argv, &error) ||
537 !g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &error))
539 g_printerr ("Error starting X server: %s", error->message);
544 process = watch_process (pid);
545 g_hash_table_insert (children, GINT_TO_POINTER (process->pid), process);
548 else if (strcmp (name, "START-VNC-CLIENT") == 0)
550 gchar *vnc_client_args, *command_line;
554 GError *error = NULL;
556 vnc_client_args = g_hash_table_lookup (params, "ARGS");
557 if (!vnc_client_args)
558 vnc_client_args = "";
559 command_line = g_strdup_printf ("%s/tests/src/vnc-client %s", BUILDDIR, vnc_client_args);
561 if (!g_shell_parse_argv (command_line, NULL, &argv, &error) ||
562 !g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &error))
564 g_printerr ("Error starting VNC client: %s", error->message);
569 process = watch_process (pid);
570 g_hash_table_insert (children, GINT_TO_POINTER (process->pid), process);
573 else if (strcmp (name, "ADD-USER") == 0)
575 gchar *status_text, *username;
578 username = g_hash_table_lookup (params, "USERNAME");
579 user = get_accounts_user_by_name (username);
581 accounts_user_set_hidden (user, FALSE, TRUE);
583 g_warning ("Unknown user %s", username);
585 status_text = g_strdup_printf ("RUNNER ADD-USER USERNAME=%s", username);
586 check_status (status_text);
587 g_free (status_text);
589 else if (strcmp (name, "DELETE-USER") == 0)
591 gchar *status_text, *username;
594 username = g_hash_table_lookup (params, "USERNAME");
595 user = get_accounts_user_by_name (username);
597 accounts_user_set_hidden (user, TRUE, TRUE);
599 g_warning ("Unknown user %s", username);
601 status_text = g_strdup_printf ("RUNNER DELETE-USER USERNAME=%s", username);
602 check_status (status_text);
603 g_free (status_text);
605 /* Forward to external processes */
606 else if (g_str_has_prefix (name, "SESSION-") ||
607 g_str_has_prefix (name, "GREETER-") ||
608 g_str_has_prefix (name, "XSERVER-") ||
609 strcmp (name, "UNITY-SYSTEM-COMPOSITOR") == 0)
612 for (link = status_clients; link; link = link->next)
614 StatusClient *client = link->data;
616 GError *error = NULL;
618 length = strlen (command);
619 if (g_socket_send (client->socket, (gchar *) &length, sizeof (length), NULL, &error) < 0 ||
620 g_socket_send (client->socket, command, strlen (command), NULL, &error) < 0)
621 g_printerr ("Failed to write to client socket: %s\n", error->message);
622 g_clear_error (&error);
627 g_printerr ("Unknown command '%s'\n", name);
632 g_hash_table_unref (params);
638 /* Stop daemon if requested */
643 /* Commands start with an asterisk */
644 line = get_script_line (NULL);
645 if (!line || line->text[0] != '*')
648 statuses = g_list_append (statuses, g_strdup (line->text));
651 handle_command (line->text + 1);
654 /* Stop at the end of the script */
655 if (get_script_line (NULL) == NULL)
660 status_timeout_cb (gpointer data)
664 line = get_script_line (NULL);
665 fail ("(timeout)", line ? line->text : NULL);
671 check_status (const gchar *status)
674 gboolean result = FALSE;
680 statuses = g_list_append (statuses, g_strdup (status));
682 if (getenv ("DEBUG"))
683 g_print ("%s\n", status);
685 /* Try and match against expected */
686 prefix = get_prefix (status);
687 line = get_script_line (prefix);
691 gchar *full_pattern = g_strdup_printf ("^%s$", line->text);
692 result = g_regex_match_simple (full_pattern, status, 0, 0);
693 g_free (full_pattern);
699 line = get_script_line (NULL);
700 fail (NULL, line ? line->text : NULL);
706 /* Restart timeout */
707 g_source_remove (status_timeout);
708 status_timeout = g_timeout_add (status_timeout_ms, status_timeout_cb, NULL);
714 status_message_cb (GSocket *socket, GIOCondition condition, StatusClient *client)
719 GError *error = NULL;
721 n_read = g_socket_receive (socket, (gchar *)&length, sizeof (length), NULL, &error);
723 n_read = g_socket_receive (socket, buffer, length, NULL, &error);
725 g_warning ("Error reading from socket: %s", error->message);
726 g_clear_error (&error);
729 status_clients = g_list_remove (status_clients, client);
730 g_object_unref (client->socket);
736 buffer[n_read] = '\0';
737 check_status (buffer);
744 status_connect_cb (gpointer data)
747 GError *error = NULL;
749 socket = g_socket_accept (status_socket, NULL, &error);
751 g_warning ("Failed to accept status connection: %s", error->message);
752 g_clear_error (&error);
755 StatusClient *client;
757 client = g_malloc0 (sizeof (StatusClient));
758 client->socket = socket;
759 client->source = g_socket_create_source (socket, G_IO_IN, NULL);
760 status_clients = g_list_append (status_clients, client);
762 g_source_set_callback (client->source, (GSourceFunc) status_message_cb, client, NULL);
763 g_source_attach (client->source, NULL);
770 load_script (const gchar *filename)
773 gchar *data, **lines;
775 if (!g_file_get_contents (filename, &data, NULL, NULL))
777 g_printerr ("Unable to load script: %s\n", filename);
781 lines = g_strsplit (data, "\n", -1);
784 /* Load lines with #? prefix as expected behaviour */
785 for (i = 0; lines[i]; i++)
787 gchar *text = g_strstrip (lines[i]);
788 if (g_str_has_prefix (text, "#?"))
791 line = g_malloc0 (sizeof (ScriptLine));
792 line->text = g_strdup (text + 2);
794 script = g_list_append (script, line);
801 handle_upower_call (GDBusConnection *connection,
803 const gchar *object_path,
804 const gchar *interface_name,
805 const gchar *method_name,
806 GVariant *parameters,
807 GDBusMethodInvocation *invocation,
810 if (strcmp (method_name, "SuspendAllowed") == 0)
812 check_status ("UPOWER SUSPEND-ALLOWED");
813 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
815 else if (strcmp (method_name, "Suspend") == 0)
817 check_status ("UPOWER SUSPEND");
818 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
820 else if (strcmp (method_name, "HibernateAllowed") == 0)
822 check_status ("UPOWER HIBERNATE-ALLOWED");
823 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
825 else if (strcmp (method_name, "Hibernate") == 0)
827 check_status ("UPOWER HIBERNATE");
828 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
831 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
835 upower_name_acquired_cb (GDBusConnection *connection,
839 const gchar *upower_interface =
841 " <interface name='org.freedesktop.UPower'>"
842 " <method name='SuspendAllowed'>"
843 " <arg name='allowed' direction='out' type='b'/>"
845 " <method name='Suspend'/>"
846 " <method name='HibernateAllowed'>"
847 " <arg name='allowed' direction='out' type='b'/>"
849 " <method name='Hibernate'/>"
852 static const GDBusInterfaceVTable upower_vtable =
856 GDBusNodeInfo *upower_info;
857 GError *error = NULL;
859 upower_info = g_dbus_node_info_new_for_xml (upower_interface, &error);
861 g_warning ("Failed to parse D-Bus interface: %s", error->message);
862 g_clear_error (&error);
865 g_dbus_connection_register_object (connection,
866 "/org/freedesktop/UPower",
867 upower_info->interfaces[0],
872 g_warning ("Failed to register UPower service: %s", error->message);
873 g_clear_error (&error);
874 g_dbus_node_info_unref (upower_info);
877 if (service_count == 0)
882 start_upower_daemon (void)
885 g_bus_own_name (G_BUS_TYPE_SYSTEM,
886 "org.freedesktop.UPower",
887 G_BUS_NAME_OWNER_FLAGS_NONE,
888 upower_name_acquired_cb,
896 open_ck_session (GVariant *params)
903 GError *error = NULL;
905 session = g_malloc0 (sizeof (CKSession));
906 ck_sessions = g_list_append (ck_sessions, session);
908 cookie = g_string_new ("ck-cookie");
909 g_variant_get (params, "a(sv)", &iter);
910 while (g_variant_iter_loop (iter, "(&sv)", &name, &value))
912 if (strcmp (name, "x11-display") == 0)
914 const gchar *display;
915 g_variant_get (value, "&s", &display);
916 g_string_append_printf (cookie, "-x%s", display);
920 session->cookie = cookie->str;
921 g_string_free (cookie, FALSE);
922 session->path = g_strdup_printf ("/org/freedesktop/ConsoleKit/Session%d", ck_session_index++);
923 session->id = g_dbus_connection_register_object (ck_connection,
925 ck_session_info->interfaces[0],
931 g_warning ("Failed to register CK Session: %s", error->message);
932 g_clear_error (&error);
938 handle_ck_call (GDBusConnection *connection,
940 const gchar *object_path,
941 const gchar *interface_name,
942 const gchar *method_name,
943 GVariant *parameters,
944 GDBusMethodInvocation *invocation,
947 if (strcmp (method_name, "CanRestart") == 0)
949 check_status ("CONSOLE-KIT CAN-RESTART");
950 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
952 else if (strcmp (method_name, "CanStop") == 0)
954 check_status ("CONSOLE-KIT CAN-STOP");
955 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
957 else if (strcmp (method_name, "CloseSession") == 0)
958 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
959 else if (strcmp (method_name, "OpenSession") == 0)
961 GVariantBuilder params;
962 g_variant_builder_init (¶ms, G_VARIANT_TYPE ("a(sv)"));
963 CKSession *session = open_ck_session (g_variant_builder_end (¶ms));
964 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", session->cookie));
966 else if (strcmp (method_name, "OpenSessionWithParameters") == 0)
968 CKSession *session = open_ck_session (g_variant_get_child_value (parameters, 0));
969 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", session->cookie));
971 else if (strcmp (method_name, "GetSessionForCookie") == 0)
976 g_variant_get (parameters, "(&s)", &cookie);
978 for (link = ck_sessions; link; link = link->next)
980 CKSession *session = link->data;
981 if (strcmp (session->cookie, cookie) != 0)
983 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", session->path));
988 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Unable to find session for cookie");
990 else if (strcmp (method_name, "Restart") == 0)
992 check_status ("CONSOLE-KIT RESTART");
993 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
995 else if (strcmp (method_name, "Stop") == 0)
997 check_status ("CONSOLE-KIT STOP");
998 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1001 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1005 /* Shared between CK and Login1 - identical signatures */
1007 handle_session_call (GDBusConnection *connection,
1008 const gchar *sender,
1009 const gchar *object_path,
1010 const gchar *interface_name,
1011 const gchar *method_name,
1012 GVariant *parameters,
1013 GDBusMethodInvocation *invocation,
1016 if (strcmp (method_name, "Lock") == 0)
1017 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1018 else if (strcmp (method_name, "Unlock") == 0)
1019 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1021 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1025 ck_name_acquired_cb (GDBusConnection *connection,
1029 const gchar *ck_interface =
1031 " <interface name='org.freedesktop.ConsoleKit.Manager'>"
1032 " <method name='CanRestart'>"
1033 " <arg name='can_restart' direction='out' type='b'/>"
1035 " <method name='CanStop'>"
1036 " <arg name='can_stop' direction='out' type='b'/>"
1038 " <method name='CloseSession'>"
1039 " <arg name='cookie' direction='in' type='s'/>"
1040 " <arg name='result' direction='out' type='b'/>"
1042 " <method name='OpenSession'>"
1043 " <arg name='cookie' direction='out' type='s'/>"
1045 " <method name='OpenSessionWithParameters'>"
1046 " <arg name='parameters' direction='in' type='a(sv)'/>"
1047 " <arg name='cookie' direction='out' type='s'/>"
1049 " <method name='GetSessionForCookie'>"
1050 " <arg name='cookie' direction='in' type='s'/>"
1051 " <arg name='ssid' direction='out' type='o'/>"
1053 " <method name='Restart'/>"
1054 " <method name='Stop'/>"
1055 " <signal name='SeatAdded'>"
1056 " <arg name='seat' type='o'/>"
1058 " <signal name='SeatRemoved'>"
1059 " <arg name='seat' type='o'/>"
1063 static const GDBusInterfaceVTable ck_vtable =
1067 const gchar *ck_session_interface =
1069 " <interface name='org.freedesktop.ConsoleKit.Session'>"
1070 " <method name='Lock'/>"
1071 " <method name='Unlock'/>"
1074 GDBusNodeInfo *ck_info;
1075 GError *error = NULL;
1077 ck_connection = connection;
1079 ck_info = g_dbus_node_info_new_for_xml (ck_interface, &error);
1081 g_warning ("Failed to parse D-Bus interface: %s", error->message);
1082 g_clear_error (&error);
1085 ck_session_info = g_dbus_node_info_new_for_xml (ck_session_interface, &error);
1087 g_warning ("Failed to parse D-Bus interface: %s", error->message);
1088 g_clear_error (&error);
1089 if (!ck_session_info)
1091 g_dbus_connection_register_object (connection,
1092 "/org/freedesktop/ConsoleKit/Manager",
1093 ck_info->interfaces[0],
1098 g_warning ("Failed to register console kit service: %s", error->message);
1099 g_clear_error (&error);
1100 g_dbus_node_info_unref (ck_info);
1103 if (service_count == 0)
1108 start_console_kit_daemon (void)
1111 g_bus_own_name (G_BUS_TYPE_SYSTEM,
1112 "org.freedesktop.ConsoleKit",
1113 G_BUS_NAME_OWNER_FLAGS_NONE,
1114 ck_name_acquired_cb,
1121 static Login1Session *
1122 open_login1_session (GDBusConnection *connection,
1125 Login1Session *session;
1126 GError *error = NULL;
1127 GDBusNodeInfo *login1_session_info;
1129 const gchar *login1_session_interface =
1131 " <interface name='org.freedesktop.login1.Session'>"
1132 " <method name='Lock'/>"
1133 " <method name='Unlock'/>"
1136 static const GDBusInterfaceVTable login1_session_vtable =
1138 handle_session_call,
1141 session = g_malloc0 (sizeof (Login1Session));
1142 login1_sessions = g_list_append (login1_sessions, session);
1144 session->path = g_strdup_printf("/org/freedesktop/login1/Session/c%d",
1145 login1_session_index++);
1149 login1_session_info = g_dbus_node_info_new_for_xml (login1_session_interface,
1152 g_warning ("Failed to parse login1 session D-Bus interface: %s",
1154 g_clear_error (&error);
1155 if (!login1_session_info)
1158 g_dbus_connection_register_object (connection,
1160 login1_session_info->interfaces[0],
1161 &login1_session_vtable,
1166 g_warning ("Failed to register login1 session: %s", error->message);
1167 g_clear_error (&error);
1168 g_dbus_node_info_unref (login1_session_info);
1175 handle_login1_call (GDBusConnection *connection,
1176 const gchar *sender,
1177 const gchar *object_path,
1178 const gchar *interface_name,
1179 const gchar *method_name,
1180 GVariant *parameters,
1181 GDBusMethodInvocation *invocation,
1185 if (strcmp (method_name, "GetSessionByPID") == 0)
1187 /* Look for a session with our PID, and create one if we don't have one
1191 Login1Session *ret = NULL;
1193 g_variant_get (parameters, "(u)", &pid);
1195 for (link = login1_sessions; link; link = link->next)
1197 Login1Session *session;
1198 session = link->data;
1199 if (session->pid == pid)
1207 ret = open_login1_session (connection, parameters);
1209 g_dbus_method_invocation_return_value (invocation,
1210 g_variant_new("(o)", ret->path));
1213 else if (strcmp (method_name, "CanReboot") == 0)
1215 check_status ("LOGIN1 CAN-REBOOT");
1216 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1218 else if (strcmp (method_name, "Reboot") == 0)
1220 gboolean interactive;
1221 g_variant_get (parameters, "(b)", &interactive);
1222 check_status ("LOGIN1 REBOOT");
1223 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1225 else if (strcmp (method_name, "CanPowerOff") == 0)
1227 check_status ("LOGIN1 CAN-POWER-OFF");
1228 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1230 else if (strcmp (method_name, "Suspend") == 0)
1232 gboolean interactive;
1233 g_variant_get (parameters, "(b)", &interactive);
1234 check_status ("LOGIN1 SUSPEND");
1235 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1237 else if (strcmp (method_name, "CanSuspend") == 0)
1239 check_status ("LOGIN1 CAN-SUSPEND");
1240 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1242 else if (strcmp (method_name, "PowerOff") == 0)
1244 gboolean interactive;
1245 g_variant_get (parameters, "(b)", &interactive);
1246 check_status ("LOGIN1 POWER-OFF");
1247 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1249 else if (strcmp (method_name, "CanHibernate") == 0)
1251 check_status ("LOGIN1 CAN-HIBERNATE");
1252 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "yes"));
1254 else if (strcmp (method_name, "Hibernate") == 0)
1256 gboolean interactive;
1257 g_variant_get (parameters, "(b)", &interactive);
1258 check_status ("LOGIN1 HIBERNATE");
1259 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1262 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1266 login1_name_acquired_cb (GDBusConnection *connection,
1270 const gchar *login1_interface =
1272 " <interface name='org.freedesktop.login1.Manager'>"
1273 " <method name='GetSessionByPID'>"
1274 " <arg name='pid' type='u' direction='in'/>"
1275 " <arg name='session' type='o' direction='out'/>"
1277 " <method name='CanReboot'>"
1278 " <arg name='result' direction='out' type='s'/>"
1280 " <method name='Reboot'>"
1281 " <arg name='interactive' direction='in' type='b'/>"
1283 " <method name='CanPowerOff'>"
1284 " <arg name='result' direction='out' type='s'/>"
1286 " <method name='PowerOff'>"
1287 " <arg name='interactive' direction='in' type='b'/>"
1289 " <method name='CanSuspend'>"
1290 " <arg name='result' direction='out' type='s'/>"
1292 " <method name='Suspend'>"
1293 " <arg name='interactive' direction='in' type='b'/>"
1295 " <method name='CanHibernate'>"
1296 " <arg name='result' direction='out' type='s'/>"
1298 " <method name='Hibernate'>"
1299 " <arg name='interactive' direction='in' type='b'/>"
1303 static const GDBusInterfaceVTable login1_vtable =
1307 GDBusNodeInfo *login1_info;
1308 GError *error = NULL;
1310 login1_info = g_dbus_node_info_new_for_xml (login1_interface, &error);
1312 g_warning ("Failed to parse login1 D-Bus interface: %s", error->message);
1313 g_clear_error (&error);
1316 g_dbus_connection_register_object (connection,
1317 "/org/freedesktop/login1",
1318 login1_info->interfaces[0],
1323 g_warning ("Failed to register login1 service: %s", error->message);
1324 g_clear_error (&error);
1325 g_dbus_node_info_unref (login1_info);
1328 if (service_count == 0)
1333 start_login1_daemon (void)
1336 g_bus_own_name (G_BUS_TYPE_SYSTEM,
1337 "org.freedesktop.login1",
1338 G_BUS_NAME_OWNER_FLAGS_NONE,
1339 login1_name_acquired_cb,
1346 static AccountsUser *
1347 get_accounts_user_by_uid (guint uid)
1351 for (link = accounts_users; link; link = link->next)
1353 AccountsUser *u = link->data;
1361 static AccountsUser *
1362 get_accounts_user_by_name (const gchar *username)
1366 for (link = accounts_users; link; link = link->next)
1368 AccountsUser *u = link->data;
1369 if (strcmp (u->user_name, username) == 0)
1377 accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal)
1379 GError *error = NULL;
1381 user->hidden = hidden;
1383 if (user->hidden && user->id != 0)
1385 g_dbus_connection_unregister_object (accounts_connection, user->id);
1386 g_dbus_connection_emit_signal (accounts_connection,
1388 "/org/freedesktop/Accounts",
1389 "org.freedesktop.Accounts",
1391 g_variant_new ("(o)", user->path),
1394 g_warning ("Failed to emit UserDeleted: %s", error->message);
1395 g_clear_error (&error);
1399 if (!user->hidden && user->id == 0)
1401 user->id = g_dbus_connection_register_object (accounts_connection,
1403 user_info->interfaces[0],
1409 g_warning ("Failed to register user: %s", error->message);
1410 g_clear_error (&error);
1412 g_dbus_connection_emit_signal (accounts_connection,
1414 "/org/freedesktop/Accounts",
1415 "org.freedesktop.Accounts",
1417 g_variant_new ("(o)", user->path),
1420 g_warning ("Failed to emit UserAdded: %s", error->message);
1421 g_clear_error (&error);
1426 load_passwd_file (void)
1428 gchar *path, *data, **lines;
1429 gchar **user_filter = NULL;
1432 if (g_key_file_has_key (config, "test-runner-config", "accounts-service-user-filter", NULL))
1436 filter = g_key_file_get_string (config, "test-runner-config", "accounts-service-user-filter", NULL);
1437 user_filter = g_strsplit (filter, " ", -1);
1441 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
1442 g_file_get_contents (path, &data, NULL, NULL);
1444 lines = g_strsplit (data, "\n", -1);
1447 for (i = 0; lines[i]; i++)
1451 gchar *user_name, *real_name;
1452 AccountsUser *user = NULL;
1454 fields = g_strsplit (lines[i], ":", -1);
1455 if (fields == NULL || g_strv_length (fields) < 7)
1457 g_strfreev (fields);
1461 user_name = fields[0];
1462 uid = atoi (fields[2]);
1463 real_name = fields[4];
1465 user = get_accounts_user_by_uid (uid);
1469 GKeyFile *dmrc_file;
1471 user = g_malloc0 (sizeof (AccountsUser));
1472 accounts_users = g_list_append (accounts_users, user);
1474 /* Only allow users in whitelist */
1475 user->hidden = FALSE;
1480 user->hidden = TRUE;
1481 for (j = 0; user_filter[j] != NULL; j++)
1482 if (strcmp (user_name, user_filter[j]) == 0)
1483 user->hidden = FALSE;
1486 dmrc_file = g_key_file_new ();
1487 path = g_build_filename (temp_dir, "home", user_name, ".dmrc", NULL);
1488 g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
1492 user->user_name = g_strdup (user_name);
1493 user->real_name = g_strdup (real_name);
1494 user->home_directory = g_build_filename (temp_dir, "home", user_name, NULL);
1495 user->language = g_key_file_get_string (dmrc_file, "Desktop", "Language", NULL);
1496 /* DMRC contains a locale, strip the codeset off it to get the language */
1499 gchar *c = strchr (user->language, '.');
1503 user->xsession = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL);
1504 user->layouts = g_key_file_get_string_list (dmrc_file, "X-Accounts", "Layouts", NULL, NULL);
1505 user->path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", uid);
1506 accounts_user_set_hidden (user, user->hidden, FALSE);
1508 g_key_file_free (dmrc_file);
1511 g_strfreev (fields);
1518 handle_accounts_call (GDBusConnection *connection,
1519 const gchar *sender,
1520 const gchar *object_path,
1521 const gchar *interface_name,
1522 const gchar *method_name,
1523 GVariant *parameters,
1524 GDBusMethodInvocation *invocation,
1527 if (strcmp (method_name, "ListCachedUsers") == 0)
1529 GVariantBuilder builder;
1532 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
1534 load_passwd_file ();
1535 for (link = accounts_users; link; link = link->next)
1537 AccountsUser *user = link->data;
1539 g_variant_builder_add_value (&builder, g_variant_new_object_path (user->path));
1542 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ao)", &builder));
1544 else if (strcmp (method_name, "FindUserByName") == 0)
1546 AccountsUser *user = NULL;
1549 g_variant_get (parameters, "(&s)", &user_name);
1551 load_passwd_file ();
1552 user = get_accounts_user_by_name (user_name);
1553 if (user && !user->hidden)
1554 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", user->path));
1556 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such user: %s", user_name);
1559 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1563 handle_user_call (GDBusConnection *connection,
1564 const gchar *sender,
1565 const gchar *object_path,
1566 const gchar *interface_name,
1567 const gchar *method_name,
1568 GVariant *parameters,
1569 GDBusMethodInvocation *invocation,
1572 AccountsUser *user = user_data;
1574 if (strcmp (method_name, "SetXSession") == 0)
1578 g_variant_get (parameters, "(&s)", &xsession);
1580 g_free (user->xsession);
1581 user->xsession = g_strdup (xsession);
1583 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1586 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such method: %s", method_name);
1590 handle_user_get_property (GDBusConnection *connection,
1591 const gchar *sender,
1592 const gchar *object_path,
1593 const gchar *interface_name,
1594 const gchar *property_name,
1598 AccountsUser *user = user_data;
1600 if (strcmp (property_name, "UserName") == 0)
1601 return g_variant_new_string (user->user_name);
1602 else if (strcmp (property_name, "RealName") == 0)
1603 return g_variant_new_string (user->real_name);
1604 else if (strcmp (property_name, "HomeDirectory") == 0)
1605 return g_variant_new_string (user->home_directory);
1606 else if (strcmp (property_name, "BackgroundFile") == 0)
1607 return g_variant_new_string ("");
1608 else if (strcmp (property_name, "Language") == 0)
1609 return g_variant_new_string (user->language ? user->language : "");
1610 else if (strcmp (property_name, "XSession") == 0)
1611 return g_variant_new_string (user->xsession ? user->xsession : "");
1612 else if (strcmp (property_name, "XKeyboardLayouts") == 0)
1614 if (user->layouts != NULL)
1615 return g_variant_new_strv ((const gchar * const *) user->layouts, -1);
1617 return g_variant_new_strv (NULL, 0);
1619 else if (strcmp (property_name, "XHasMessages") == 0)
1620 return g_variant_new_boolean (FALSE);
1626 accounts_name_acquired_cb (GDBusConnection *connection,
1630 const gchar *accounts_interface =
1632 " <interface name='org.freedesktop.Accounts'>"
1633 " <method name='ListCachedUsers'>"
1634 " <arg name='user' direction='out' type='ao'/>"
1636 " <method name='FindUserByName'>"
1637 " <arg name='name' direction='in' type='s'/>"
1638 " <arg name='user' direction='out' type='o'/>"
1640 " <signal name='UserAdded'>"
1641 " <arg name='user' type='o'/>"
1643 " <signal name='UserDeleted'>"
1644 " <arg name='user' type='o'/>"
1648 static const GDBusInterfaceVTable accounts_vtable =
1650 handle_accounts_call,
1652 const gchar *user_interface =
1654 " <interface name='org.freedesktop.Accounts.User'>"
1655 " <method name='SetXSession'>"
1656 " <arg name='x_session' direction='in' type='s'/>"
1658 " <property name='UserName' type='s' access='read'/>"
1659 " <property name='RealName' type='s' access='read'/>"
1660 " <property name='HomeDirectory' type='s' access='read'/>"
1661 " <property name='BackgroundFile' type='s' access='read'/>"
1662 " <property name='Language' type='s' access='read'/>"
1663 " <property name='XSession' type='s' access='read'/>"
1664 " <property name='XKeyboardLayouts' type='as' access='read'/>"
1665 " <property name='XHasMessages' type='b' access='read'/>"
1668 GError *error = NULL;
1670 accounts_connection = connection;
1672 accounts_info = g_dbus_node_info_new_for_xml (accounts_interface, &error);
1674 g_warning ("Failed to parse D-Bus interface: %s", error->message);
1675 g_clear_error (&error);
1678 user_info = g_dbus_node_info_new_for_xml (user_interface, &error);
1680 g_warning ("Failed to parse D-Bus interface: %s", error->message);
1681 g_clear_error (&error);
1684 g_dbus_connection_register_object (connection,
1685 "/org/freedesktop/Accounts",
1686 accounts_info->interfaces[0],
1692 g_warning ("Failed to register accounts service: %s", error->message);
1693 g_clear_error (&error);
1694 g_dbus_node_info_unref (accounts_info);
1697 if (service_count == 0)
1702 start_accounts_service_daemon (void)
1705 g_bus_own_name (G_BUS_TYPE_SYSTEM,
1706 "org.freedesktop.Accounts",
1707 G_BUS_NAME_OWNER_FLAGS_NONE,
1708 accounts_name_acquired_cb,
1718 GString *command_line;
1719 gchar **lightdm_argv;
1721 GError *error = NULL;
1725 status_timeout = g_timeout_add (status_timeout_ms, status_timeout_cb, NULL);
1727 command_line = g_string_new ("lightdm");
1728 if (getenv ("DEBUG"))
1729 g_string_append (command_line, " --debug");
1730 g_string_append_printf (command_line, " --cache-dir %s/cache", temp_dir);
1732 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",
1733 g_getenv ("PATH"), g_getenv ("LD_PRELOAD"), g_getenv ("LD_LIBRARY_PATH"), g_getenv ("LIGHTDM_TEST_ROOT"), g_getenv ("DBUS_SESSION_BUS_ADDRESS"),
1736 if (!g_shell_parse_argv (command_line->str, NULL, &lightdm_argv, &error))
1738 g_warning ("Error parsing command line: %s", error->message);
1739 quit (EXIT_FAILURE);
1741 g_clear_error (&error);
1743 if (!g_spawn_async (NULL, lightdm_argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &lightdm_pid, &error))
1745 g_warning ("Error launching LightDM: %s", error->message);
1746 quit (EXIT_FAILURE);
1748 g_clear_error (&error);
1749 lightdm_process = watch_process (lightdm_pid);
1751 check_status ("RUNNER DAEMON-START");
1755 signal_cb (gpointer user_data)
1757 g_print ("Caught signal, quitting\n");
1758 quit (EXIT_FAILURE);
1763 main (int argc, char **argv)
1767 gchar *greeter = NULL, *script_name, *config_file, *additional_config, *path, *path1, *path2, *ld_preload, *ld_library_path, *home_dir;
1768 GString *passwd_data, *group_data;
1769 GSource *status_source;
1771 GError *error = NULL;
1773 #if !defined(GLIB_VERSION_2_36)
1777 loop = g_main_loop_new (NULL, FALSE);
1779 g_unix_signal_add (SIGINT, signal_cb, NULL);
1780 g_unix_signal_add (SIGTERM, signal_cb, NULL);
1782 children = g_hash_table_new (g_direct_hash, g_direct_equal);
1786 g_printerr ("Usage %s SCRIPT-NAME GREETER\n", argv[0]);
1787 quit (EXIT_FAILURE);
1789 script_name = argv[1];
1790 config_file = g_strdup_printf ("%s.conf", script_name);
1791 config_path = g_build_filename (SRCDIR, "tests", "scripts", config_file, NULL);
1792 g_free (config_file);
1794 config = g_key_file_new ();
1795 g_key_file_load_from_file (config, config_path, G_KEY_FILE_NONE, NULL);
1797 load_script (config_path);
1799 if (!getcwd (cwd, 1024))
1801 g_critical ("Error getting current directory: %s", strerror (errno));
1802 quit (EXIT_FAILURE);
1805 /* Don't contact our X server */
1806 g_unsetenv ("DISPLAY");
1808 /* Override system calls */
1809 ld_preload = g_build_filename (BUILDDIR, "tests", "src", ".libs", "libsystem.so", NULL);
1810 g_setenv ("LD_PRELOAD", ld_preload, TRUE);
1811 g_free (ld_preload);
1813 /* Run test programs */
1814 path = g_strdup_printf ("%s/tests/src/.libs:%s/tests/src:%s/tests/src:%s/src:%s", BUILDDIR, BUILDDIR, SRCDIR, BUILDDIR, g_getenv ("PATH"));
1815 g_setenv ("PATH", path, TRUE);
1818 /* Use locally built libraries */
1819 path1 = g_build_filename (BUILDDIR, "liblightdm-gobject", ".libs", NULL);
1820 path2 = g_build_filename (BUILDDIR, "liblightdm-qt", ".libs", NULL);
1821 ld_library_path = g_strdup_printf ("%s:%s", path1, path2);
1824 g_setenv ("LD_LIBRARY_PATH", ld_library_path, TRUE);
1825 g_free (ld_library_path);
1826 path1 = g_build_filename (BUILDDIR, "liblightdm-gobject", NULL);
1827 g_setenv ("GI_TYPELIB_PATH", path1, TRUE);
1830 /* Run in a temporary directory inside the build directory */
1831 /* Note we have to pick a name that is short since Unix sockets in this directory have a 108 character limit on their paths */
1836 name = g_strdup_printf (".r%d", i);
1838 temp_dir = g_build_filename ("/tmp", name, NULL);
1840 if (!g_file_test (temp_dir, G_FILE_TEST_EXISTS))
1844 g_mkdir_with_parents (temp_dir, 0755);
1845 g_setenv ("LIGHTDM_TEST_ROOT", temp_dir, TRUE);
1847 /* Open socket for status */
1848 /* Note we have to pick a socket name that is short since there is a 108 character limit on the name */
1849 status_socket_name = g_build_filename (temp_dir, ".s", NULL);
1850 unlink (status_socket_name);
1851 status_socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
1853 g_warning ("Error creating status socket %s: %s", status_socket_name, error->message);
1854 g_clear_error (&error);
1857 GSocketAddress *address;
1860 address = g_unix_socket_address_new (status_socket_name);
1861 result = g_socket_bind (status_socket, address, FALSE, &error);
1862 g_object_unref (address);
1864 g_warning ("Error binding status socket %s: %s", status_socket_name, error->message);
1865 g_clear_error (&error);
1868 result = g_socket_listen (status_socket, &error);
1870 g_warning ("Error listening on status socket %s: %s", status_socket_name, error->message);
1871 g_clear_error (&error);
1875 g_object_unref (status_socket);
1876 status_socket = NULL;
1880 quit (EXIT_FAILURE);
1881 status_source = g_socket_create_source (status_socket, G_IO_IN, NULL);
1882 g_source_set_callback (status_source, status_connect_cb, NULL, NULL);
1883 g_source_attach (status_source, NULL);
1885 /* Set up a skeleton file system */
1886 g_mkdir_with_parents (g_strdup_printf ("%s/etc", temp_dir), 0755);
1887 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share", temp_dir), 0755);
1888 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/sessions", temp_dir), 0755);
1889 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/remote-sessions", temp_dir), 0755);
1890 g_mkdir_with_parents (g_strdup_printf ("%s/usr/share/lightdm/greeters", temp_dir), 0755);
1891 g_mkdir_with_parents (g_strdup_printf ("%s/tmp", temp_dir), 0755);
1892 g_mkdir_with_parents (g_strdup_printf ("%s/var/run", temp_dir), 0755);
1893 g_mkdir_with_parents (g_strdup_printf ("%s/var/log", temp_dir), 0755);
1895 /* Copy over the configuration */
1896 g_mkdir_with_parents (g_strdup_printf ("%s/etc/lightdm", temp_dir), 0755);
1897 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))
1898 if (system (g_strdup_printf ("cp %s %s/etc/lightdm/lightdm.conf", config_path, temp_dir)))
1899 perror ("Failed to copy configuration");
1901 additional_config = g_key_file_get_string (config, "test-runner-config", "additional-config", NULL);
1902 if (additional_config)
1906 g_mkdir_with_parents (g_strdup_printf ("%s/etc/lightdm/lightdm.conf.d", temp_dir), 0755);
1908 files = g_strsplit (additional_config, " ", -1);
1909 for (i = 0; files[i]; i++)
1910 if (system (g_strdup_printf ("cp %s/tests/scripts/%s %s/etc/lightdm/lightdm.conf.d", SRCDIR, files[i], temp_dir)))
1911 perror ("Failed to copy configuration");
1915 /* Always copy the script */
1916 if (system (g_strdup_printf ("cp %s %s/script", config_path, temp_dir)))
1917 perror ("Failed to copy configuration");
1919 /* Copy over the greeter files */
1920 if (system (g_strdup_printf ("cp %s/sessions/* %s/usr/share/lightdm/sessions", DATADIR, temp_dir)))
1921 perror ("Failed to copy sessions");
1922 if (system (g_strdup_printf ("cp %s/remote-sessions/* %s/usr/share/lightdm/remote-sessions", DATADIR, temp_dir)))
1923 perror ("Failed to copy remote sessions");
1924 if (system (g_strdup_printf ("cp %s/greeters/* %s/usr/share/lightdm/greeters", DATADIR, temp_dir)))
1925 perror ("Failed to copy greeters");
1927 /* Set up the default greeter */
1928 path = g_build_filename (temp_dir, "usr", "share", "lightdm", "greeters", "default.desktop", NULL);
1929 greeter = g_strdup_printf ("%s.desktop", argv[2]);
1930 if (symlink (greeter, path) < 0)
1932 g_printerr ("Failed to make greeter symlink %s->%s: %s\n", path, greeter, strerror (errno));
1933 quit (EXIT_FAILURE);
1938 home_dir = g_build_filename (temp_dir, "home", NULL);
1940 /* Make fake users */
1945 gboolean have_home_dir;
1949 gchar *dbus_layouts;
1955 {"root", "", TRUE, "root", NULL, NULL, NULL, NULL, 0},
1956 /* Unprivileged account for greeters */
1957 {"lightdm", "", TRUE, "", NULL, NULL, NULL, NULL, 100},
1958 /* These accounts have a password */
1959 {"have-password1", "password", TRUE, "Password User 1", NULL, NULL, NULL, NULL, 1000},
1960 {"have-password2", "password", TRUE, "Password User 2", NULL, NULL, NULL, NULL, 1001},
1961 {"have-password3", "password", TRUE, "Password User 3", NULL, NULL, NULL, NULL, 1002},
1962 {"have-password4", "password", TRUE, "Password User 4", NULL, NULL, NULL, NULL, 1003},
1963 /* This account always prompts for a password, even if using the lightdm-autologin service */
1964 {"always-password", "password", TRUE, "Password User 4", NULL, NULL, NULL, NULL, 1004},
1965 /* These accounts have no password */
1966 {"no-password1", "", TRUE, "No Password User 1", NULL, NULL, NULL, NULL, 1005},
1967 {"no-password2", "", TRUE, "No Password User 2", NULL, NULL, NULL, NULL, 1006},
1968 {"no-password3", "", TRUE, "No Password User 3", NULL, NULL, NULL, NULL, 1007},
1969 {"no-password4", "", TRUE, "No Password User 4", NULL, NULL, NULL, NULL, 1008},
1970 /* This account has a keyboard layout */
1971 {"have-layout", "", TRUE, "Layout User", NULL, "us", NULL, NULL, 1009},
1972 /* This account has a set of keyboard layouts */
1973 {"have-layouts", "", TRUE, "Layouts User", NULL, "ru", "fr\toss;ru;", NULL, 1010},
1974 /* This account has a language set */
1975 {"have-language", "", TRUE, "Language User", NULL, NULL, NULL, "en_AU.utf8", 1011},
1976 /* This account has a preconfigured session */
1977 {"have-session", "", TRUE, "Session User", "alternative", NULL, NULL, NULL, 1012},
1978 /* This account has the home directory mounted on login */
1979 {"mount-home-dir", "", FALSE, "Mounted Home Dir User", NULL, NULL, NULL, NULL, 1013},
1980 /* This account is denied access */
1981 {"denied", "", TRUE, "Denied User", NULL, NULL, NULL, NULL, 1014},
1982 /* This account has expired */
1983 {"expired", "", TRUE, "Expired User", NULL, NULL, NULL, NULL, 1015},
1984 /* This account needs a password change */
1985 {"new-authtok", "", TRUE, "New Token User", NULL, NULL, NULL, NULL, 1016},
1986 /* This account is switched to change-user2 when authentication succeeds */
1987 {"change-user1", "", TRUE, "Change User 1", NULL, NULL, NULL, NULL, 1017},
1988 {"change-user2", "", TRUE, "Change User 2", NULL, NULL, NULL, NULL, 1018},
1989 /* This account switches to invalid-user when authentication succeeds */
1990 {"change-user-invalid", "", TRUE, "Invalid Change User",NULL, NULL, NULL, NULL, 1019},
1991 /* This account crashes on authentication */
1992 {"crash-authenticate", "", TRUE, "Crash Auth User", NULL, NULL, NULL, NULL, 1020},
1993 /* This account shows an informational prompt on login */
1994 {"info-prompt", "password", TRUE, "Info Prompt", NULL, NULL, NULL, NULL, 1021},
1995 /* This account shows multiple informational prompts on login */
1996 {"multi-info-prompt","password", TRUE, "Multi Info Prompt", NULL, NULL, NULL, NULL, 1022},
1997 /* This account uses two factor authentication */
1998 {"two-factor", "password", TRUE, "Two Factor", NULL, NULL, NULL, NULL, 1023},
1999 /* This account has a special group */
2000 {"group-member", "password", TRUE, "Group Member", NULL, NULL, NULL, NULL, 1024},
2001 /* This account has the home directory created when the session starts */
2002 {"make-home-dir", "", FALSE, "Make Home Dir User", NULL, NULL, NULL, NULL, 1025},
2003 /* This account fails to open a session */
2004 {"session-error", "password", TRUE, "Session Error", NULL, NULL, NULL, NULL, 1026},
2005 /* This account can't establish credentials */
2006 {"cred-error", "password", TRUE, "Cred Error", NULL, NULL, NULL, NULL, 1027},
2007 /* This account has expired credentials */
2008 {"cred-expired", "password", TRUE, "Cred Expired", NULL, NULL, NULL, NULL, 1028},
2009 /* This account has cannot access their credentials */
2010 {"cred-unavail", "password", TRUE, "Cred Unavail", NULL, NULL, NULL, NULL, 1029},
2011 /* This account sends informational messages for each PAM function that is called */
2012 {"log-pam", "password", TRUE, "Log PAM", NULL, NULL, NULL, NULL, 1030},
2013 /* This account shows multiple prompts on login */
2014 {"multi-prompt", "password", TRUE, "Multi Prompt", NULL, NULL, NULL, NULL, 1031},
2015 {NULL, NULL, FALSE, NULL, NULL, NULL, NULL, NULL, 0}
2017 passwd_data = g_string_new ("");
2018 group_data = g_string_new ("");
2019 for (i = 0; users[i].user_name; i++)
2021 GKeyFile *dmrc_file;
2022 gboolean save_dmrc = FALSE;
2024 if (users[i].have_home_dir)
2026 path = g_build_filename (home_dir, users[i].user_name, NULL);
2027 g_mkdir_with_parents (path, 0755);
2028 if (chown (path, users[i].uid, users[i].uid) < 0)
2029 g_debug ("chown (%s) failed: %s", path, strerror (errno));
2033 dmrc_file = g_key_file_new ();
2034 if (users[i].xsession)
2036 g_key_file_set_string (dmrc_file, "Desktop", "Session", users[i].xsession);
2039 if (users[i].dmrc_layout)
2041 g_key_file_set_string (dmrc_file, "Desktop", "Layout", users[i].dmrc_layout);
2044 if (users[i].dbus_layouts)
2046 g_key_file_set_string (dmrc_file, "X-Accounts", "Layouts", users[i].dbus_layouts);
2050 if (users[i].language)
2052 g_key_file_set_string (dmrc_file, "Desktop", "Language", users[i].language);
2060 path = g_build_filename (home_dir, users[i].user_name, ".dmrc", NULL);
2061 data = g_key_file_to_data (dmrc_file, NULL, NULL);
2062 g_file_set_contents (path, data, -1, NULL);
2067 g_key_file_free (dmrc_file);
2069 /* Add passwd file entry */
2070 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);
2072 /* Add group file entry */
2073 g_string_append_printf (group_data, "%s:x:%d:%s\n", users[i].user_name, users[i].uid, users[i].user_name);
2075 path = g_build_filename (temp_dir, "etc", "passwd", NULL);
2076 g_file_set_contents (path, passwd_data->str, -1, NULL);
2078 g_string_free (passwd_data, TRUE);
2080 /* Add an extra test group */
2081 g_string_append_printf (group_data, "test-group:x:111:\n");
2083 path = g_build_filename (temp_dir, "etc", "group", NULL);
2084 g_file_set_contents (path, group_data->str, -1, NULL);
2086 g_string_free (group_data, TRUE);
2088 if (g_key_file_has_key (config, "test-runner-config", "timeout", NULL))
2089 status_timeout_ms = g_key_file_get_integer (config, "test-runner-config", "timeout", NULL) * 1000;
2091 /* Start D-Bus services */
2092 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-upower", NULL))
2093 start_upower_daemon ();
2094 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-console-kit", NULL))
2095 start_console_kit_daemon ();
2096 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-login1", NULL))
2097 start_login1_daemon ();
2098 if (!g_key_file_get_boolean (config, "test-runner-config", "disable-accounts-service", NULL))
2099 start_accounts_service_daemon ();
2101 g_main_loop_run (loop);
2103 return EXIT_FAILURE;