]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - tests/src/unity-system-compositor.c
2f8e42cd6f5f81ee960cd61af51a238c9a292149
[sojka/lightdm.git] / tests / src / unity-system-compositor.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <glib-unix.h>
7
8 #include "status.h"
9
10 static GMainLoop *loop;
11 static int exit_status = EXIT_SUCCESS;
12 static int from_dm_fd = -1, to_dm_fd = -1;
13
14 static GKeyFile *config;
15
16 static void
17 quit (int status)
18 {
19     exit_status = status;
20     g_main_loop_quit (loop);
21 }
22
23 static gboolean
24 sigint_cb (gpointer user_data)
25 {
26     status_notify ("UNITY-SYSTEM-COMPOSITOR TERMINATE SIGNAL=%d", SIGINT);
27     quit (EXIT_SUCCESS);
28     return TRUE;
29 }
30
31 static gboolean
32 sigterm_cb (gpointer user_data)
33 {
34     status_notify ("UNITY-SYSTEM-COMPOSITOR TERMINATE SIGNAL=%d", SIGTERM);
35     quit (EXIT_SUCCESS);
36     return TRUE;
37 }
38
39 typedef enum
40 {
41    USC_MESSAGE_PING = 0,
42    USC_MESSAGE_PONG = 1,
43    USC_MESSAGE_READY = 2,
44    USC_MESSAGE_SESSION_CONNECTED = 3,
45    USC_MESSAGE_SET_ACTIVE_SESSION = 4
46 } USCMessageID;
47
48 static void
49 write_message (guint16 id, const guint8 *payload, guint16 payload_length)
50 {
51     guint8 *data;
52     gsize data_length = 4 + payload_length;
53
54     data = g_malloc (data_length);
55     data[0] = id >> 8;
56     data[1] = id & 0xFF;
57     data[2] = payload_length >> 8;
58     data[3] = payload_length & 0xFF;
59     memcpy (data + 4, payload, payload_length);
60
61     if (write (to_dm_fd, data, data_length) < 0)
62         fprintf (stderr, "Failed to write to daemon: %s\n", strerror (errno));
63 }
64
65 static gboolean
66 read_message_cb (GIOChannel *channel, GIOCondition condition, gpointer data)
67 {
68     gchar header[4], *payload;
69     gsize n_read;
70     guint16 id;
71     guint16 payload_length;
72     GError *error = NULL;
73
74     if (g_io_channel_read_chars (channel, header, 4, &n_read, &error) != G_IO_STATUS_NORMAL)
75     {
76         g_printerr ("Failed to read header: %s\n", error->message);
77         return FALSE;
78     }
79     if (n_read != 4)
80     {
81         g_printerr ("Short read for header, %zi instead of expected 4\n", n_read);
82         return FALSE;
83     }
84     id = header[0] << 8 | header[1];
85     payload_length = header[2] << 8 | header[3];
86     payload = g_malloc0 (payload_length + 1);
87     if (g_io_channel_read_chars (channel, payload, payload_length, &n_read, &error) != G_IO_STATUS_NORMAL)
88     {
89         g_printerr ("Failed to read payload: %s\n", error->message);
90         return FALSE;
91     }
92     if (n_read != payload_length)
93     {
94         g_printerr ("Short read for payload, %zi instead of expected %d\n", n_read, payload_length);
95         return FALSE;      
96     }
97
98     switch (id)
99     {
100     case USC_MESSAGE_PING:
101         status_notify ("UNITY-SYSTEM-COMPOSITOR PING");
102         break;
103     case USC_MESSAGE_SET_ACTIVE_SESSION:
104         status_notify ("UNITY-SYSTEM-COMPOSITOR SET-ACTIVE-SESSION ID=%s", (gchar *)payload);
105         break;
106     default:
107         g_printerr ("Ignoring message %d with %d octets\n", id, payload_length);
108         break;
109     }
110
111     free (payload);
112
113     return TRUE;
114 }
115
116 static void
117 request_cb (const gchar *request)
118 {
119     if (!request)
120     {
121         g_main_loop_quit (loop);
122         return;
123     }
124
125     if (strcmp (request, "UNITY-SYSTEM-COMPOSITOR PING") == 0)
126         write_message (USC_MESSAGE_PING, NULL, 0);
127     else if (strcmp (request, "UNITY-SYSTEM-COMPOSITOR PONG") == 0)
128         write_message (USC_MESSAGE_PONG, NULL, 0);
129     else if (strcmp (request, "UNITY-SYSTEM-COMPOSITOR READY") == 0)
130         write_message (USC_MESSAGE_READY, NULL, 0);
131 }
132
133 int
134 main (int argc, char **argv)
135 {
136     int i;
137     GString *status_text;
138     gboolean test = FALSE;
139     int vt_number = -1;
140
141 #if !defined(GLIB_VERSION_2_36)
142     g_type_init ();
143 #endif
144
145     loop = g_main_loop_new (NULL, FALSE);
146
147     g_unix_signal_add (SIGINT, sigint_cb, NULL);
148     g_unix_signal_add (SIGTERM, sigterm_cb, NULL);
149
150     status_connect (request_cb);
151
152     for (i = 1; i < argc; i++)
153     {
154         char *arg = argv[i];
155
156         if (strcmp (arg, "--from-dm-fd") == 0)
157         {
158             from_dm_fd = atoi (argv[i+1]);
159             i++;
160         }
161         else if (strcmp (arg, "--to-dm-fd") == 0)
162         {
163             to_dm_fd = atoi (argv[i+1]);
164             i++;
165         }
166         else if (strcmp (arg, "--vt") == 0)
167         {
168             vt_number = atoi (argv[i+1]);
169             i++;
170         }
171         else if (strcmp (arg, "--test") == 0)
172             test = TRUE;
173         else
174             return EXIT_FAILURE;
175     }
176
177     g_io_add_watch (g_io_channel_unix_new (from_dm_fd), G_IO_IN, read_message_cb, NULL);
178
179     status_text = g_string_new ("UNITY-SYSTEM-COMPOSITOR START");
180     if (vt_number >= 0)
181         g_string_append_printf (status_text, " VT=%d", vt_number);
182     if (g_getenv ("XDG_VTNR"))
183         g_string_append_printf (status_text, " XDG_VTNR=%s", g_getenv ("XDG_VTNR"));
184     if (test)
185         g_string_append (status_text, " TEST=TRUE");
186     status_notify (status_text->str);
187     g_string_free (status_text, TRUE);
188
189     config = g_key_file_new ();
190     g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
191
192     if (g_key_file_has_key (config, "unity-system-compositor-config", "return-value", NULL))
193     {
194         int return_value = g_key_file_get_integer (config, "unity-system-compositor-config", "return-value", NULL);
195         status_notify ("UNITY-SYSTEM-COMPOSITOR EXIT CODE=%d", return_value);
196         return return_value;
197     }
198
199     g_main_loop_run (loop);
200
201     return exit_status;
202 }