]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - tests/src/status.c
Releasing 1.20.0
[sojka/lightdm.git] / tests / src / status.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <glib.h>
5 #include <gio/gio.h>
6 #include <gio/gunixsocketaddress.h>
7 #include <unistd.h>
8 #include <ctype.h>
9
10 #include "status.h"
11
12 static GSocket *status_socket = NULL;
13 static StatusRequestFunc request_func = NULL;
14 static gchar *filter_id = NULL;
15
16 static gboolean
17 status_request_cb (GSocket *socket, GIOCondition condition, gpointer data)
18 {
19     int length;
20     gchar buffer[1024];
21     ssize_t n_read;
22     const gchar *c, *start;
23     int l;
24     gchar *id, *name = NULL;
25     gboolean id_matches;
26     GHashTable *params;
27     GError *error = NULL;
28
29     n_read = g_socket_receive (socket, (gchar *)&length, sizeof (length), NULL, &error);
30     if (n_read > 0)
31         n_read = g_socket_receive (socket, buffer, length, NULL, &error);
32     if (error)
33     {
34         if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
35             n_read = 0;
36         else
37             g_warning ("Error reading from socket: %s", error->message);
38     }
39     g_clear_error (&error);
40     if (n_read == 0)
41     {
42         if (request_func)
43             request_func (NULL, NULL);
44         return FALSE;
45     }
46
47     if (n_read <= 0 || !request_func)
48         return TRUE;
49
50     buffer[n_read] = '\0';
51     c = buffer;
52     start = c;
53     l = 0;
54     while (*c && !isspace (*c))
55     {
56         c++;
57         l++;
58     }
59     id = g_strdup_printf ("%.*s", l, start);
60     id_matches = g_strcmp0 (id, filter_id) == 0;
61     g_free (id);
62     if (!id_matches)
63         return TRUE;
64
65     while (isspace (*c))
66         c++;
67     start = c;
68     l = 0;
69     while (*c && !isspace (*c))
70     {
71         c++;
72         l++;
73     }
74     name = g_strdup_printf ("%.*s", l, start);
75
76     params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
77     while (TRUE)
78     {
79         const gchar *start;
80         gchar *param_name, *param_value;
81
82         while (isspace (*c))
83             c++;
84         start = c;
85         while (*c && !isspace (*c) && *c != '=')
86             c++;
87         if (*c == '\0')
88             break;
89
90         param_name = g_strdup_printf ("%.*s", (int) (c - start), start);
91
92         if (*c == '=')
93         {
94             c++;
95             while (isspace (*c))
96                 c++;
97             if (*c == '\"')
98             {
99                 gboolean escaped = FALSE;
100                 GString *value;
101
102                 c++;
103                 value = g_string_new ("");
104                 while (*c)
105                 {
106                     if (*c == '\\')
107                     {
108                         if (escaped)
109                         {
110                             g_string_append_c (value, '\\');
111                             escaped = FALSE;
112                         }
113                         else
114                             escaped = TRUE;
115                     }
116                     else if (!escaped && *c == '\"')
117                         break;
118                     if (!escaped)
119                         g_string_append_c (value, *c);
120                     c++;
121                 }
122                 param_value = value->str;
123                 g_string_free (value, FALSE);
124                 if (*c == '\"')
125                     c++;
126             }
127             else
128             {
129                 start = c;
130                 while (*c && !isspace (*c))
131                     c++;
132                 param_value = g_strdup_printf ("%.*s", (int) (c - start), start);
133             }
134         }
135         else
136             param_value = g_strdup ("");
137
138         g_hash_table_insert (params, param_name, param_value);
139     }
140
141     request_func (name, params);
142
143     g_free (name);
144     g_hash_table_unref (params);
145
146     return TRUE;
147 }
148
149 gboolean
150 status_connect (StatusRequestFunc request_cb, const gchar *id)
151 {
152     gchar *path;
153     GSocketAddress *address;
154     gboolean result;
155     GSource *source;
156     GError *error = NULL;
157
158     request_func = request_cb;
159     filter_id = g_strdup (id);
160
161     status_socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
162     if (error)
163         g_printerr ("Unable to open socket for status: %s\n", error->message);
164     g_clear_error (&error);
165     if (!status_socket)
166         return FALSE;
167
168     path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), ".s", NULL);
169     address = g_unix_socket_address_new (path);
170     result = g_socket_connect (status_socket, address, NULL, &error);
171     g_object_unref (address);
172     if (error)
173         g_printerr ("Failed to connect to status socket %s: %s\n", path, error->message);
174     g_clear_error (&error);
175     g_free (path);
176     if (!result)
177     {
178         g_object_unref (status_socket);
179         status_socket = NULL;
180         return FALSE;
181     }
182
183     source = g_socket_create_source (status_socket, G_IO_IN, NULL);
184     g_source_set_callback (source, (GSourceFunc) status_request_cb, NULL, NULL);
185     g_source_attach (source, NULL);
186
187     return TRUE;
188 }
189
190 void
191 status_notify (const gchar *format, ...)
192 {
193     gboolean written = FALSE;
194
195     gchar status[1024];
196     va_list ap;
197
198     va_start (ap, format);
199     vsnprintf (status, 1024, format, ap);
200     va_end (ap);
201
202     if (status_socket)
203     {
204         GError *error = NULL;
205         int length;
206
207         length = strlen (status);
208         written = g_socket_send (status_socket, (gchar *) &length, sizeof (length), NULL, &error) == sizeof (length) &&
209                   g_socket_send (status_socket, status, strlen (status), NULL, &error) == strlen (status);
210         if (error)
211             g_printerr ("Failed to write to status socket: %s\n", error->message);
212         g_clear_error (&error);
213     }
214
215     if (!written)
216         g_printerr ("%s\n", status);
217 }