]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - tests/src/Xvnc.c
Remove trailing whitespace
[sojka/lightdm.git] / tests / src / Xvnc.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <gio/gio.h>
9 #include <glib-unix.h>
10
11 #include "status.h"
12 #include "x-server.h"
13 #include "x-authority.h"
14
15 static GMainLoop *loop;
16
17 static GKeyFile *config;
18
19 /* Path to lock file */
20 static gchar *lock_path = NULL;
21
22 /* Path to authority database to use */
23 static gchar *auth_path = NULL;
24
25 /* ID to use for test reporting */
26 static gchar *id;
27
28 /* Display number being served */
29 static int display_number = 0;
30
31 /* X server */
32 static XServer *xserver = NULL;
33
34 static void
35 cleanup (void)
36 {
37     if (lock_path)
38         unlink (lock_path);
39     if (xserver)
40         g_object_unref (xserver);
41 }
42
43 static void
44 quit (int status)
45 {
46     cleanup ();
47     exit (status);
48 }
49
50 static gboolean
51 sighup_cb (gpointer user_data)
52 {
53     status_notify ("%s DISCONNECT-CLIENTS", id);
54     return TRUE;
55 }
56
57 static gboolean
58 sigint_cb (gpointer user_data)
59 {
60     status_notify ("%s TERMINATE SIGNAL=%d", id, SIGINT);
61     quit (EXIT_SUCCESS);
62     return TRUE;
63 }
64
65 static gboolean
66 sigterm_cb (gpointer user_data)
67 {
68     status_notify ("%s TERMINATE SIGNAL=%d", id, SIGTERM);
69     quit (EXIT_SUCCESS);
70     return TRUE;
71 }
72
73 static void
74 client_connected_cb (XServer *server, XClient *client)
75 {
76     gchar *auth_error = NULL;
77
78     status_notify ("%s ACCEPT-CONNECT", id);
79
80     if (auth_error)
81         x_client_send_failed (client, auth_error);
82     else
83         x_client_send_success (client);
84     g_free (auth_error);
85 }
86
87 static void
88 client_disconnected_cb (XServer *server, XClient *client)
89 {
90     g_signal_handlers_disconnect_matched (client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NULL);
91 }
92
93 static gboolean
94 vnc_data_cb (GIOChannel *channel, GIOCondition condition, gpointer data)
95 {
96     gchar buffer[1024];
97     gsize n_read;
98     GIOStatus status;
99     GError *error = NULL;
100
101     status = g_io_channel_read_chars (channel, buffer, 1023, &n_read, &error);
102     if (error)
103         g_warning ("Error reading from VNC client: %s", error->message);
104     g_clear_error (&error);
105
106     if (status == G_IO_STATUS_NORMAL)
107     {
108         buffer[n_read] = '\0';
109         if (g_str_has_suffix (buffer, "\n"))
110             buffer[n_read-1] = '\0';
111         status_notify ("%s VNC-CLIENT-CONNECT VERSION=\"%s\"", id, buffer);
112     }
113
114     return TRUE;
115 }
116
117 static void
118 request_cb (const gchar *name, GHashTable *params)
119 {
120     if (!name)
121     {
122         g_main_loop_quit (loop);
123         return;
124     }
125
126     if (strcmp (name, "INDICATE-READY") == 0)
127     {
128         void *handler;
129
130         handler = signal (SIGUSR1, SIG_IGN);
131         if (handler == SIG_IGN)
132         {
133             status_notify ("%s INDICATE-READY", id);
134             kill (getppid (), SIGUSR1);
135         }
136         signal (SIGUSR1, handler);
137     }
138
139     else if (strcmp (name, "START-VNC") == 0)
140     {
141         /* Send server protocol version to client */
142         g_print ("RFB 003.007\n");
143     }
144 }
145
146 int
147 main (int argc, char **argv)
148 {
149     char *pid_string;
150     gboolean use_inetd = FALSE;
151     gboolean has_option = FALSE;
152     gchar *geometry = g_strdup ("640x480");
153     gint depth = 8;
154     gchar *lock_filename;
155     int lock_file;
156     int i;
157
158 #if !defined(GLIB_VERSION_2_36)
159     g_type_init ();
160 #endif
161
162     loop = g_main_loop_new (NULL, FALSE);
163
164     g_unix_signal_add (SIGINT, sigint_cb, NULL);
165     g_unix_signal_add (SIGTERM, sigterm_cb, NULL);
166     g_unix_signal_add (SIGHUP, sighup_cb, NULL);
167
168     for (i = 1; i < argc; i++)
169     {
170         char *arg = argv[i];
171
172         if (arg[0] == ':')
173         {
174             display_number = atoi (arg + 1);
175         }
176         else if (strcmp (arg, "-auth") == 0)
177         {
178             auth_path = argv[i+1];
179             i++;
180         }
181         else if (strcmp (arg, "-nolisten") == 0)
182         {
183             char *protocol = argv[i+1];
184             i++;
185             if (strcmp (protocol, "tcp") == 0)
186                 ;//listen_tcp = FALSE;
187             else if (strcmp (protocol, "unix") == 0)
188                 ;//listen_unix = FALSE;
189         }
190         else if (strcmp (arg, "-geometry") == 0)
191         {
192             g_free (geometry);
193             geometry = g_strdup (argv[i+1]);
194             i++;
195         }
196         else if (strcmp (arg, "-depth") == 0)
197         {
198             depth = atoi (argv[i+1]);
199             i++;
200         }
201         else if (strcmp (arg, "-inetd") == 0)
202         {
203             use_inetd = TRUE;
204         }
205         else if (strcmp (arg, "-option") == 0)
206         {
207             has_option = TRUE;
208         }
209         else
210         {
211             g_printerr ("Unrecognized option: %s\n"
212                         "Use: %s [:<display>] [option]\n"
213                         "-auth file             Select authorization file\n"
214                         "-nolisten protocol     Don't listen on protocol\n"
215                         "-geometry WxH          Set framebuffer width & height\n"
216                         "-depth D               Set framebuffer depth\n"
217                         "-inetd                 Xvnc is launched by inetd\n",
218                         arg, argv[0]);
219             return EXIT_FAILURE;
220         }
221     }
222
223     id = g_strdup_printf ("XSERVER-%d", display_number);
224
225     status_connect (request_cb, id);
226
227     xserver = x_server_new (display_number);
228     g_signal_connect (xserver, "client-connected", G_CALLBACK (client_connected_cb), NULL);
229     g_signal_connect (xserver, "client-disconnected", G_CALLBACK (client_disconnected_cb), NULL);
230
231     status_notify ("%s START GEOMETRY=%s DEPTH=%d OPTION=%s", id, geometry, depth, has_option ? "TRUE" : "FALSE");
232
233     config = g_key_file_new ();
234     g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
235
236     if (use_inetd)
237     {
238         if (!g_io_add_watch (g_io_channel_unix_new (STDIN_FILENO), G_IO_IN, vnc_data_cb, NULL))
239             return EXIT_FAILURE;
240     }
241     else
242     {
243         g_printerr ("Only supported in -inetd mode\n");
244         return EXIT_FAILURE;
245     }
246
247     lock_filename = g_strdup_printf (".X%d-lock", display_number);
248     lock_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", lock_filename, NULL);
249     g_free (lock_filename);
250     lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
251     if (lock_file < 0)
252     {
253         fprintf (stderr,
254                  "Fatal server error:\n"
255                  "Server is already active for display %d\n"
256                  "      If this server is no longer running, remove %s\n"
257                  "      and start again.\n", display_number, lock_path);
258         g_free (lock_path);
259         lock_path = NULL;
260         quit (EXIT_FAILURE);
261     }
262     pid_string = g_strdup_printf ("%10ld", (long) getpid ());
263     if (write (lock_file, pid_string, strlen (pid_string)) < 0)
264     {
265         g_warning ("Error writing PID file: %s", strerror (errno));
266         quit (EXIT_FAILURE);
267     }
268     g_free (pid_string);
269
270     if (!x_server_start (xserver))
271         quit (EXIT_FAILURE);
272
273     g_main_loop_run (loop);
274
275     cleanup ();
276
277     return EXIT_SUCCESS;
278 }