10 #include <glib-unix.h>
14 #include "x-authority.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 XServer *xserver = NULL;
42 g_object_unref (xserver);
49 g_main_loop_quit (loop);
53 sighup_cb (gpointer user_data)
55 status_notify ("%s DISCONNECT-CLIENTS", id);
60 sigint_cb (gpointer user_data)
62 status_notify ("%s TERMINATE SIGNAL=%d", id, SIGINT);
68 sigterm_cb (gpointer user_data)
70 status_notify ("%s TERMINATE SIGNAL=%d", id, SIGTERM);
76 client_connected_cb (XServer *server, XClient *client)
78 status_notify ("%s ACCEPT-CONNECT", id);
79 x_client_send_success (client);
83 client_disconnected_cb (XServer *server, XClient *client)
85 g_signal_handlers_disconnect_matched (client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NULL);
89 vnc_data_cb (GIOChannel *channel, GIOCondition condition, gpointer data)
96 status = g_io_channel_read_chars (channel, buffer, 1023, &n_read, &error);
98 g_warning ("Error reading from VNC client: %s", error->message);
99 g_clear_error (&error);
101 if (status == G_IO_STATUS_NORMAL)
103 buffer[n_read] = '\0';
104 if (g_str_has_suffix (buffer, "\n"))
105 buffer[n_read-1] = '\0';
106 status_notify ("%s VNC-CLIENT-CONNECT VERSION=\"%s\"", id, buffer);
113 request_cb (const gchar *name, GHashTable *params)
117 g_main_loop_quit (loop);
121 if (strcmp (name, "INDICATE-READY") == 0)
125 handler = signal (SIGUSR1, SIG_IGN);
126 if (handler == SIG_IGN)
128 status_notify ("%s INDICATE-READY", id);
129 kill (getppid (), SIGUSR1);
131 signal (SIGUSR1, handler);
134 else if (strcmp (name, "START-VNC") == 0)
136 /* Send server protocol version to client */
137 g_print ("RFB 003.007\n");
142 main (int argc, char **argv)
146 gboolean use_inetd = FALSE;
147 gboolean has_option = FALSE;
148 gchar *geometry = g_strdup ("640x480");
150 gchar *lock_filename;
153 #if !defined(GLIB_VERSION_2_36)
157 loop = g_main_loop_new (NULL, FALSE);
159 g_unix_signal_add (SIGINT, sigint_cb, NULL);
160 g_unix_signal_add (SIGTERM, sigterm_cb, NULL);
161 g_unix_signal_add (SIGHUP, sighup_cb, NULL);
163 for (i = 1; i < argc; i++)
169 display_number = atoi (arg + 1);
171 else if (strcmp (arg, "-auth") == 0)
173 auth_path = argv[i+1];
176 else if (strcmp (arg, "-nolisten") == 0)
178 char *protocol = argv[i+1];
180 if (strcmp (protocol, "tcp") == 0)
181 ;//listen_tcp = FALSE;
182 else if (strcmp (protocol, "unix") == 0)
183 ;//listen_unix = FALSE;
185 else if (strcmp (arg, "-geometry") == 0)
188 geometry = g_strdup (argv[i+1]);
191 else if (strcmp (arg, "-depth") == 0)
193 depth = atoi (argv[i+1]);
196 else if (strcmp (arg, "-inetd") == 0)
200 else if (strcmp (arg, "-option") == 0)
206 g_printerr ("Unrecognized option: %s\n"
207 "Use: %s [:<display>] [option]\n"
208 "-auth file Select authorization file\n"
209 "-nolisten protocol Don't listen on protocol\n"
210 "-geometry WxH Set framebuffer width & height\n"
211 "-depth D Set framebuffer depth\n"
212 "-inetd Xvnc is launched by inetd\n",
218 id = g_strdup_printf ("XVNC-%d", display_number);
220 status_connect (request_cb, id);
222 xserver = x_server_new (display_number);
223 g_signal_connect (xserver, X_SERVER_SIGNAL_CLIENT_CONNECTED, G_CALLBACK (client_connected_cb), NULL);
224 g_signal_connect (xserver, X_SERVER_SIGNAL_CLIENT_DISCONNECTED, G_CALLBACK (client_disconnected_cb), NULL);
226 status_notify ("%s START GEOMETRY=%s DEPTH=%d OPTION=%s", id, geometry, depth, has_option ? "TRUE" : "FALSE");
228 config = g_key_file_new ();
229 g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
233 if (!g_io_add_watch (g_io_channel_unix_new (STDIN_FILENO), G_IO_IN, vnc_data_cb, NULL))
238 g_printerr ("Only supported in -inetd mode\n");
242 lock_filename = g_strdup_printf (".X%d-lock", display_number);
243 lock_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", lock_filename, NULL);
244 g_free (lock_filename);
245 lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
248 char *lock_contents = NULL;
250 if (g_file_get_contents (lock_path, &lock_contents, NULL, NULL))
252 gchar *proc_filename;
255 pid = atol (lock_contents);
256 g_free (lock_contents);
258 proc_filename = g_strdup_printf ("/proc/%d", pid);
259 if (!g_file_test (proc_filename, G_FILE_TEST_EXISTS))
262 gchar *socket_filename;
265 socket_dir = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", ".X11-unix", NULL);
266 g_mkdir_with_parents (socket_dir, 0755);
268 socket_filename = g_strdup_printf ("X%d", display_number);
269 socket_path = g_build_filename (socket_dir, socket_filename, NULL);
271 g_printerr ("Breaking lock on non-existant process %d\n", pid);
273 unlink (socket_path);
276 g_free (socket_filename);
277 g_free (socket_path);
279 g_free (proc_filename);
281 lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
287 "Fatal server error:\n"
288 "Server is already active for display %d\n"
289 " If this server is no longer running, remove %s\n"
290 " and start again.\n", display_number, lock_path);
295 pid_string = g_strdup_printf ("%10ld", (long) getpid ());
296 if (write (lock_file, pid_string, strlen (pid_string)) < 0)
298 g_warning ("Error writing PID file: %s", strerror (errno));
303 if (!x_server_start (xserver))
306 g_main_loop_run (loop);