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 /* Path to lock file */
22 static gchar *lock_path = NULL;
24 /* Path to authority database to use */
25 static gchar *auth_path = NULL;
27 /* ID to use for test reporting */
30 /* Display number being served */
31 static int display_number = 0;
34 static int vt_number = -1;
37 static XServer *xserver = NULL;
40 static XDMCPClient *xdmcp_client = NULL;
42 /* Authorization provided by XDMCP server */
43 static guint16 xdmcp_cookie_length = 0;
44 static guint8 *xdmcp_cookie = NULL;
52 g_object_unref (xserver);
54 g_object_unref (xdmcp_client);
61 g_main_loop_quit (loop);
65 sighup_cb (gpointer user_data)
67 status_notify ("%s DISCONNECT-CLIENTS", id);
72 sigint_cb (gpointer user_data)
74 status_notify ("%s TERMINATE SIGNAL=%d", id, SIGINT);
80 sigterm_cb (gpointer user_data)
82 status_notify ("%s TERMINATE SIGNAL=%d", id, SIGTERM);
88 xdmcp_query_cb (XDMCPClient *client)
90 static gboolean notified_query = FALSE;
94 status_notify ("%s SEND-QUERY", id);
95 notified_query = TRUE;
100 xdmcp_willing_cb (XDMCPClient *client, XDMCPWilling *message)
102 gchar **authorization_names;
103 GInetAddress *addresses[2];
105 status_notify ("%s GOT-WILLING AUTHENTICATION-NAME=\"%s\" HOSTNAME=\"%s\" STATUS=\"%s\"", id, message->authentication_name, message->hostname, message->status);
107 status_notify ("%s SEND-REQUEST DISPLAY-NUMBER=%d AUTHORIZATION-NAME=\"%s\" MFID=\"%s\"", id, display_number, "MIT-MAGIC-COOKIE-1", "TEST XSERVER");
109 authorization_names = g_strsplit ("MIT-MAGIC-COOKIE-1", " ", -1);
110 addresses[0] = xdmcp_client_get_local_address (client);
112 xdmcp_client_send_request (client, display_number,
115 authorization_names, "TEST XSERVER");
116 g_strfreev (authorization_names);
120 xdmcp_accept_cb (XDMCPClient *client, XDMCPAccept *message)
122 status_notify ("%s GOT-ACCEPT SESSION-ID=%d AUTHENTICATION-NAME=\"%s\" AUTHORIZATION-NAME=\"%s\"", id, message->session_id, message->authentication_name, message->authorization_name);
124 /* Ignore if haven't picked a valid authorization */
125 if (strcmp (message->authorization_name, "MIT-MAGIC-COOKIE-1") != 0)
128 g_free (xdmcp_cookie);
129 xdmcp_cookie_length = message->authorization_data_length;
130 xdmcp_cookie = g_malloc (message->authorization_data_length);
131 memcpy (xdmcp_cookie, message->authorization_data, message->authorization_data_length);
133 status_notify ("%s SEND-MANAGE SESSION-ID=%d DISPLAY-NUMBER=%d DISPLAY-CLASS=\"%s\"", id, message->session_id, display_number, "DISPLAY CLASS");
134 xdmcp_client_send_manage (client, message->session_id, display_number, "DISPLAY CLASS");
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))
198 main (int argc, char **argv)
202 gboolean do_xdmcp = FALSE;
203 guint xdmcp_port = 0;
204 gchar *xdmcp_host = NULL;
206 gchar *mir_id = NULL;
207 gchar *lock_filename;
208 gboolean sharevts = FALSE;
210 GString *status_text;
212 #if !defined(GLIB_VERSION_2_36)
216 loop = g_main_loop_new (NULL, FALSE);
218 g_unix_signal_add (SIGINT, sigint_cb, NULL);
219 g_unix_signal_add (SIGTERM, sigterm_cb, NULL);
220 g_unix_signal_add (SIGHUP, sighup_cb, NULL);
222 for (i = 1; i < argc; i++)
228 display_number = atoi (arg + 1);
230 else if (strcmp (arg, "-auth") == 0)
232 auth_path = argv[i+1];
235 else if (strcmp (arg, "-nolisten") == 0)
237 char *protocol = argv[i+1];
239 if (strcmp (protocol, "tcp") == 0)
240 ;//listen_tcp = FALSE;
241 else if (strcmp (protocol, "unix") == 0)
242 ;//listen_unix = FALSE;
244 else if (strcmp (arg, "-nr") == 0)
247 else if (strcmp (arg, "-background") == 0)
252 else if (strcmp (arg, "-port") == 0)
254 xdmcp_port = atoi (argv[i+1]);
257 else if (strcmp (arg, "-query") == 0)
260 xdmcp_host = argv[i+1];
263 else if (strcmp (arg, "-broadcast") == 0)
267 else if (g_str_has_prefix (arg, "vt"))
269 vt_number = atoi (arg + 2);
271 else if (strcmp (arg, "-novtswitch") == 0)
275 else if (strcmp (arg, "-seat") == 0)
280 else if (strcmp (arg, "-sharevts") == 0)
284 else if (strcmp (arg, "-mir") == 0)
289 else if (strcmp (arg, "-mirSocket") == 0)
296 g_printerr ("Unrecognized option: %s\n"
297 "Use: %s [:<display>] [option]\n"
298 "-auth file Select authorization file\n"
299 "-nolisten protocol Don't listen on protocol\n"
300 "-background [none] Create root window with no background\n"
301 "-nr (Ubuntu-specific) Synonym for -background none\n"
302 "-query host-name Contact named host for XDMCP\n"
303 "-broadcast Broadcast for XDMCP\n"
304 "-port port-num UDP port number to send messages to\n"
305 "-seat string seat to run on\n"
306 "-sharevts share VTs with another X server\n"
307 "-mir id Mir ID to use\n"
308 "-mirSocket name Mir socket to use\n"
309 "vtxx Use virtual terminal xx instead of the next available\n",
315 id = g_strdup_printf ("XSERVER-%d", display_number);
317 status_connect (request_cb, id);
319 xserver = x_server_new (display_number);
320 g_signal_connect (xserver, "client-connected", G_CALLBACK (client_connected_cb), NULL);
321 g_signal_connect (xserver, "client-disconnected", G_CALLBACK (client_disconnected_cb), NULL);
323 status_text = g_string_new ("");
324 g_string_printf (status_text, "%s START", id);
326 g_string_append_printf (status_text, " VT=%d", vt_number);
328 g_string_append_printf (status_text, " SEAT=%s", seat);
330 g_string_append (status_text, " SHAREVTS=TRUE");
332 g_string_append_printf (status_text, " MIR-ID=%s", mir_id);
333 status_notify ("%s", status_text->str);
334 g_string_free (status_text, TRUE);
336 config = g_key_file_new ();
337 g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
339 if (g_key_file_has_key (config, "test-xserver-config", "return-value", NULL))
341 int return_value = g_key_file_get_integer (config, "test-xserver-config", "return-value", NULL);
342 status_notify ("%s EXIT CODE=%d", id, return_value);
346 lock_filename = g_strdup_printf (".X%d-lock", display_number);
347 lock_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", lock_filename, NULL);
348 g_free (lock_filename);
349 lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
352 char *lock_contents = NULL;
354 if (g_file_get_contents (lock_path, &lock_contents, NULL, NULL))
356 gchar *proc_filename;
359 pid = atol (lock_contents);
360 g_free (lock_contents);
362 proc_filename = g_strdup_printf ("/proc/%d", pid);
363 if (!g_file_test (proc_filename, G_FILE_TEST_EXISTS))
366 gchar *socket_filename;
369 socket_dir = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", ".X11-unix", NULL);
370 g_mkdir_with_parents (socket_dir, 0755);
372 socket_filename = g_strdup_printf ("X%d", display_number);
373 socket_path = g_build_filename (socket_dir, socket_filename, NULL);
375 g_printerr ("Breaking lock on non-existant process %d\n", pid);
377 unlink (socket_path);
380 g_free (socket_filename);
381 g_free (socket_path);
383 g_free (proc_filename);
385 lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
391 "Fatal server error:\n"
392 "Server is already active for display %d\n"
393 " If this server is no longer running, remove %s\n"
394 " and start again.\n", display_number, lock_path);
399 pid_string = g_strdup_printf ("%10ld", (long) getpid ());
400 if (write (lock_file, pid_string, strlen (pid_string)) < 0)
402 g_warning ("Error writing PID file: %s", strerror (errno));
407 if (!x_server_start (xserver))
413 xdmcp_client = xdmcp_client_new ();
415 xdmcp_client_set_hostname (xdmcp_client, xdmcp_host);
417 xdmcp_client_set_port (xdmcp_client, xdmcp_port);
418 g_signal_connect (xdmcp_client, "query", G_CALLBACK (xdmcp_query_cb), NULL);
419 g_signal_connect (xdmcp_client, "willing", G_CALLBACK (xdmcp_willing_cb), NULL);
420 g_signal_connect (xdmcp_client, "accept", G_CALLBACK (xdmcp_accept_cb), NULL);
421 g_signal_connect (xdmcp_client, "decline", G_CALLBACK (xdmcp_decline_cb), NULL);
422 g_signal_connect (xdmcp_client, "failed", G_CALLBACK (xdmcp_failed_cb), NULL);
425 g_main_loop_run (loop);