13 #include "x-authority.h"
14 #include "xdmcp-client.h"
16 static GMainLoop *loop;
17 static int exit_status = EXIT_SUCCESS;
19 static GKeyFile *config;
21 /* Version to pretend to be */
22 static gchar *xorg_version;
23 static gint xorg_version_major, xorg_version_minor;
25 /* Path to lock file */
26 static gchar *lock_path = NULL;
28 /* TRUE if we allow TCP connections */
29 static gboolean listen_tcp = TRUE;
31 /* TRUE if we allow Unix connections */
32 static gboolean listen_unix = TRUE;
34 /* Configuration to use */
35 static gchar *config_file = NULL;
37 /* Configuration layout to use */
38 static gchar *layout = NULL;
40 /* Path to authority database to use */
41 static gchar *auth_path = NULL;
43 /* ID to use for test reporting */
46 /* Display number being served */
47 static int display_number = 0;
50 static int vt_number = -1;
53 static XServer *xserver = NULL;
56 static XDMCPClient *xdmcp_client = NULL;
58 /* Session ID provided by XDMCP server */
59 static guint32 xdmcp_session_id = 0;
61 /* Authorization provided by XDMCP server */
62 static guint16 xdmcp_cookie_length = 0;
63 static guint8 *xdmcp_cookie = NULL;
71 g_object_unref (xserver);
73 g_object_unref (xdmcp_client);
80 g_main_loop_quit (loop);
84 sighup_cb (gpointer user_data)
86 status_notify ("%s DISCONNECT-CLIENTS", id);
91 sigint_cb (gpointer user_data)
93 status_notify ("%s TERMINATE SIGNAL=%d", id, SIGINT);
99 sigterm_cb (gpointer user_data)
101 status_notify ("%s TERMINATE SIGNAL=%d", id, SIGTERM);
107 xdmcp_query_cb (XDMCPClient *client)
109 static gboolean notified_query = FALSE;
113 status_notify ("%s SEND-QUERY", id);
114 notified_query = TRUE;
119 xdmcp_willing_cb (XDMCPClient *client, XDMCPWilling *message)
121 status_notify ("%s GOT-WILLING AUTHENTICATION-NAME=\"%s\" HOSTNAME=\"%s\" STATUS=\"%s\"", id, message->authentication_name, message->hostname, message->status);
125 xdmcp_accept_cb (XDMCPClient *client, XDMCPAccept *message)
127 status_notify ("%s GOT-ACCEPT SESSION-ID=%d AUTHENTICATION-NAME=\"%s\" AUTHORIZATION-NAME=\"%s\"", id, message->session_id, message->authentication_name, message->authorization_name);
129 xdmcp_session_id = message->session_id;
131 g_free (xdmcp_cookie);
132 xdmcp_cookie_length = message->authorization_data_length;
133 xdmcp_cookie = g_malloc (message->authorization_data_length);
134 memcpy (xdmcp_cookie, message->authorization_data, message->authorization_data_length);
138 xdmcp_decline_cb (XDMCPClient *client, XDMCPDecline *message)
140 status_notify ("%s GOT-DECLINE STATUS=\"%s\" AUTHENTICATION-NAME=\"%s\"", id, message->status, message->authentication_name);
144 xdmcp_failed_cb (XDMCPClient *client, XDMCPFailed *message)
146 status_notify ("%s GOT-FAILED SESSION-ID=%d STATUS=\"%s\"", id, message->session_id, message->status);
150 client_connected_cb (XServer *server, XClient *client)
152 status_notify ("%s ACCEPT-CONNECT", id);
153 x_client_send_success (client);
157 client_disconnected_cb (XServer *server, XClient *client)
159 g_signal_handlers_disconnect_matched (client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NULL);
163 request_cb (const gchar *name, GHashTable *params)
167 g_main_loop_quit (loop);
171 if (strcmp (name, "CRASH") == 0)
174 kill (getpid (), SIGSEGV);
177 else if (strcmp (name, "INDICATE-READY") == 0)
181 handler = signal (SIGUSR1, SIG_IGN);
182 if (handler == SIG_IGN)
184 status_notify ("%s INDICATE-READY", id);
185 kill (getppid (), SIGUSR1);
187 signal (SIGUSR1, handler);
190 else if (strcmp (name, "START-XDMCP") == 0)
192 if (!xdmcp_client_start (xdmcp_client))
196 else if (strcmp (name, "SEND-REQUEST") == 0)
198 const gchar *addresses_list, *authorization_names_list, *mfid;
199 gchar **list, **authorization_names;
202 GInetAddress **addresses;
204 addresses_list = g_hash_table_lookup (params, "ADDRESSES");
207 authorization_names_list = g_hash_table_lookup (params, "AUTHORIZATION-NAMES");
208 if (!authorization_names_list)
209 authorization_names_list = "";
210 mfid = g_hash_table_lookup (params, "MFID");
214 list = g_strsplit (addresses_list, " ", -1);
215 list_length = g_strv_length (list);
216 addresses = g_malloc (sizeof (GInetAddress *) * (list_length + 1));
217 for (i = 0; i < list_length; i++)
218 addresses[i] = g_inet_address_new_from_string (list[i]);
222 authorization_names = g_strsplit (authorization_names_list, " ", -1);
224 xdmcp_client_send_request (xdmcp_client, display_number,
227 authorization_names, mfid);
228 g_strfreev (authorization_names);
231 else if (strcmp (name, "SEND-MANAGE") == 0)
233 xdmcp_client_send_manage (xdmcp_client, xdmcp_session_id, display_number, "DISPLAY CLASS");
238 version_compare (int major, int minor)
240 if (major == xorg_version_major)
241 return xorg_version_minor - minor;
243 return xorg_version_major - major;
247 main (int argc, char **argv)
252 gboolean do_xdmcp = FALSE;
253 guint xdmcp_port = 0;
254 gchar *xdmcp_host = NULL;
256 gchar *mir_id = NULL;
257 gchar *lock_filename;
259 GString *status_text;
261 #if !defined(GLIB_VERSION_2_36)
265 loop = g_main_loop_new (NULL, FALSE);
267 g_unix_signal_add (SIGINT, sigint_cb, NULL);
268 g_unix_signal_add (SIGTERM, sigterm_cb, NULL);
269 g_unix_signal_add (SIGHUP, sighup_cb, NULL);
271 config = g_key_file_new ();
272 g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
274 xorg_version = g_key_file_get_string (config, "test-xserver-config", "version", NULL);
276 xorg_version = g_strdup ("1.17.0");
277 tokens = g_strsplit (xorg_version, ".", -1);
278 xorg_version_major = g_strv_length (tokens) > 0 ? atoi (tokens[0]) : 0;
279 xorg_version_minor = g_strv_length (tokens) > 1 ? atoi (tokens[1]) : 0;
282 /* TCP listening default changed in 1.17.0 */
283 listen_tcp = version_compare (1, 17) < 0;
285 for (i = 1; i < argc; i++)
291 display_number = atoi (arg + 1);
293 else if (strcmp (arg, "-config") == 0)
295 config_file = argv[i+1];
298 else if (strcmp (arg, "-layout") == 0)
303 else if (strcmp (arg, "-auth") == 0)
305 auth_path = argv[i+1];
308 else if (strcmp (arg, "-listen") == 0 && version_compare (1, 17) >= 0)
310 char *protocol = argv[i+1];
312 if (strcmp (protocol, "tcp") == 0)
314 else if (strcmp (protocol, "unix") == 0)
317 else if (strcmp (arg, "-nolisten") == 0)
319 char *protocol = argv[i+1];
321 if (strcmp (protocol, "tcp") == 0)
323 else if (strcmp (protocol, "unix") == 0)
326 else if (strcmp (arg, "-nr") == 0)
329 else if (strcmp (arg, "-background") == 0)
334 else if (strcmp (arg, "-port") == 0)
336 xdmcp_port = atoi (argv[i+1]);
339 else if (strcmp (arg, "-query") == 0)
342 xdmcp_host = argv[i+1];
346 else if (strcmp (arg, "-broadcast") == 0)
351 else if (g_str_has_prefix (arg, "vt"))
353 vt_number = atoi (arg + 2);
355 else if (strcmp (arg, "-novtswitch") == 0)
359 else if (strcmp (arg, "-seat") == 0)
364 else if (strcmp (arg, "-mir") == 0)
369 else if (strcmp (arg, "-mirSocket") == 0)
374 else if (strcmp (arg, "-version") == 0)
376 fprintf (stderr, "\nX.Org X Server %s\nBlah blah blah\n", xorg_version);
381 g_printerr ("Unrecognized option: %s\n"
382 "Use: %s [:<display>] [option]\n"
383 "-config file Specify a configuration file\n"
384 "-layout name Specify the ServerLayout section name\n"
385 "-auth file Select authorization file\n"
386 "-nolisten protocol Don't listen on protocol\n"
387 "-listen protocol Listen on protocol\n"
388 "-background [none] Create root window with no background\n"
389 "-nr (Ubuntu-specific) Synonym for -background none\n"
390 "-query host-name Contact named host for XDMCP\n"
391 "-broadcast Broadcast for XDMCP\n"
392 "-port port-num UDP port number to send messages to\n"
393 "-seat string seat to run on\n"
394 "-mir id Mir ID to use\n"
395 "-mirSocket name Mir socket to use\n"
396 "-version show the server version\n"
397 "vtxx Use virtual terminal xx instead of the next available\n",
403 id = g_strdup_printf ("XSERVER-%d", display_number);
405 status_connect (request_cb, id);
407 xserver = x_server_new (display_number);
408 g_signal_connect (xserver, X_SERVER_SIGNAL_CLIENT_CONNECTED, G_CALLBACK (client_connected_cb), NULL);
409 g_signal_connect (xserver, X_SERVER_SIGNAL_CLIENT_DISCONNECTED, G_CALLBACK (client_disconnected_cb), NULL);
411 status_text = g_string_new ("");
412 g_string_printf (status_text, "%s START", id);
414 g_string_append_printf (status_text, " CONFIG=%s", config_file);
416 g_string_append_printf (status_text, " LAYOUT=%s", layout);
418 g_string_append_printf (status_text, " VT=%d", vt_number);
420 g_string_append (status_text, " LISTEN-TCP");
422 g_string_append (status_text, " NO-LISTEN-UNIX");
424 g_string_append_printf (status_text, " SEAT=%s", seat);
426 g_string_append_printf (status_text, " MIR-ID=%s", mir_id);
427 status_notify ("%s", status_text->str);
428 g_string_free (status_text, TRUE);
430 if (g_key_file_has_key (config, "test-xserver-config", "return-value", NULL))
432 int return_value = g_key_file_get_integer (config, "test-xserver-config", "return-value", NULL);
433 status_notify ("%s EXIT CODE=%d", id, return_value);
437 lock_filename = g_strdup_printf (".X%d-lock", display_number);
438 lock_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", lock_filename, NULL);
439 g_free (lock_filename);
440 lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
443 char *lock_contents = NULL;
445 if (g_file_get_contents (lock_path, &lock_contents, NULL, NULL))
447 gchar *proc_filename;
450 pid = atol (lock_contents);
451 g_free (lock_contents);
453 proc_filename = g_strdup_printf ("/proc/%d", pid);
454 if (!g_file_test (proc_filename, G_FILE_TEST_EXISTS))
457 gchar *socket_filename;
460 socket_dir = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", ".X11-unix", NULL);
461 g_mkdir_with_parents (socket_dir, 0755);
463 socket_filename = g_strdup_printf ("X%d", display_number);
464 socket_path = g_build_filename (socket_dir, socket_filename, NULL);
466 g_printerr ("Breaking lock on non-existant process %d\n", pid);
468 unlink (socket_path);
471 g_free (socket_filename);
472 g_free (socket_path);
474 g_free (proc_filename);
476 lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
482 "Fatal server error:\n"
483 "Server is already active for display %d\n"
484 " If this server is no longer running, remove %s\n"
485 " and start again.\n", display_number, lock_path);
490 pid_string = g_strdup_printf ("%10ld", (long) getpid ());
491 if (write (lock_file, pid_string, strlen (pid_string)) < 0)
493 g_warning ("Error writing PID file: %s", strerror (errno));
498 if (!x_server_start (xserver))
504 xdmcp_client = xdmcp_client_new ();
506 xdmcp_client_set_hostname (xdmcp_client, xdmcp_host);
508 xdmcp_client_set_port (xdmcp_client, xdmcp_port);
509 g_signal_connect (xdmcp_client, XDMCP_CLIENT_SIGNAL_QUERY, G_CALLBACK (xdmcp_query_cb), NULL);
510 g_signal_connect (xdmcp_client, XDMCP_CLIENT_SIGNAL_WILLING, G_CALLBACK (xdmcp_willing_cb), NULL);
511 g_signal_connect (xdmcp_client, XDMCP_CLIENT_SIGNAL_ACCEPT, G_CALLBACK (xdmcp_accept_cb), NULL);
512 g_signal_connect (xdmcp_client, XDMCP_CLIENT_SIGNAL_DECLINE, G_CALLBACK (xdmcp_decline_cb), NULL);
513 g_signal_connect (xdmcp_client, XDMCP_CLIENT_SIGNAL_FAILED, G_CALLBACK (xdmcp_failed_cb), NULL);
516 g_main_loop_run (loop);