chiark / gitweb /
logind: implement generic multi-session
[elogind.git] / src / libsystemd-bus / bus-internal.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "bus-internal.h"
23
24 bool object_path_is_valid(const char *p) {
25         const char *q;
26         bool slash;
27
28         if (!p)
29                 return false;
30
31         if (p[0] != '/')
32                 return false;
33
34         if (p[1] == 0)
35                 return true;
36
37         for (slash = true, q = p+1; *q; q++)
38                 if (*q == '/') {
39                         if (slash)
40                                 return false;
41
42                         slash = true;
43                 } else {
44                         bool good;
45
46                         good =
47                                 (*q >= 'a' && *q <= 'z') ||
48                                 (*q >= 'A' && *q <= 'Z') ||
49                                 (*q >= '0' && *q <= '9') ||
50                                 *q == '_';
51
52                         if (!good)
53                                 return false;
54
55                         slash = false;
56                 }
57
58         if (slash)
59                 return false;
60
61         return true;
62 }
63
64 bool interface_name_is_valid(const char *p) {
65         const char *q;
66         bool dot, found_dot;
67
68         if (isempty(p))
69                 return false;
70
71         for (dot = true, q = p; *q; q++)
72                 if (*q == '.') {
73                         if (dot)
74                                 return false;
75
76                         found_dot = dot = true;
77                 } else {
78                         bool good;
79
80                         good =
81                                 (*q >= 'a' && *q <= 'z') ||
82                                 (*q >= 'A' && *q <= 'Z') ||
83                                 (!dot && *q >= '0' && *q <= '9') ||
84                                 *q == '_';
85
86                         if (!good)
87                                 return false;
88
89                         dot = false;
90                 }
91
92         if (q - p > 255)
93                 return false;
94
95         if (dot)
96                 return false;
97
98         if (!found_dot)
99                 return false;
100
101         return true;
102 }
103
104 bool service_name_is_valid(const char *p) {
105         const char *q;
106         bool dot, found_dot, unique;
107
108         if (isempty(p))
109                 return false;
110
111         unique = p[0] == ':';
112
113         for (dot = true, q = unique ? p+1 : p; *q; q++)
114                 if (*q == '.') {
115                         if (dot)
116                                 return false;
117
118                         found_dot = dot = true;
119                 } else {
120                         bool good;
121
122                         good =
123                                 (*q >= 'a' && *q <= 'z') ||
124                                 (*q >= 'A' && *q <= 'Z') ||
125                                 ((!dot || unique) && *q >= '0' && *q <= '9') ||
126                                 *q == '_' || *q == '-';
127
128                         if (!good)
129                                 return false;
130
131                         dot = false;
132                 }
133
134         if (q - p > 255)
135                 return false;
136
137         if (dot)
138                 return false;
139
140         if (!found_dot)
141                 return false;
142
143         return true;
144 }
145
146 bool member_name_is_valid(const char *p) {
147         const char *q;
148
149         if (isempty(p))
150                 return false;
151
152         for (q = p; *q; q++) {
153                 bool good;
154
155                 good =
156                         (*q >= 'a' && *q <= 'z') ||
157                         (*q >= 'A' && *q <= 'Z') ||
158                         (*q >= '0' && *q <= '9') ||
159                         *q == '_';
160
161                 if (!good)
162                         return false;
163         }
164
165         if (q - p > 255)
166                 return false;
167
168         return true;
169 }
170
171 static bool complex_pattern_check(char c, const char *a, const char *b) {
172         bool separator = false;
173
174         if (!a && !b)
175                 return true;
176
177         if (!a || !b)
178                 return false;
179
180         for (;;) {
181                 if (*a != *b)
182                         return (separator && (*a == 0 || *b == 0)) ||
183                                 (*a == 0 && *b == c && b[1] == 0) ||
184                                 (*b == 0 && *a == c && a[1] == 0);
185
186                 if (*a == 0)
187                         return true;
188
189                 separator = *a == c;
190
191                 a++, b++;
192         }
193 }
194
195 bool namespace_complex_pattern(const char *pattern, const char *value) {
196         return complex_pattern_check('.', pattern, value);
197 }
198
199 bool path_complex_pattern(const char *pattern, const char *value) {
200         return complex_pattern_check('/', pattern, value);
201 }
202
203 static bool simple_pattern_check(char c, const char *a, const char *b) {
204
205         if (!a && !b)
206                 return true;
207
208         if (!a || !b)
209                 return false;
210
211         for (;;) {
212                 if (*a != *b)
213                         return *a == 0 && *b == c;
214
215                 if (*a == 0)
216                         return true;
217
218                 a++, b++;
219         }
220 }
221
222 bool namespace_simple_pattern(const char *pattern, const char *value) {
223         return simple_pattern_check('.', pattern, value);
224 }
225
226 bool path_simple_pattern(const char *pattern, const char *value) {
227         return simple_pattern_check('/', pattern, value);
228 }
229
230 int bus_message_type_from_string(const char *s, uint8_t *u) {
231         if (streq(s, "signal"))
232                 *u = SD_BUS_MESSAGE_TYPE_SIGNAL;
233         else if (streq(s, "method_call"))
234                 *u = SD_BUS_MESSAGE_TYPE_METHOD_CALL;
235         else if (streq(s, "error"))
236                 *u = SD_BUS_MESSAGE_TYPE_METHOD_ERROR;
237         else if (streq(s, "method_return"))
238                 *u = SD_BUS_MESSAGE_TYPE_METHOD_RETURN;
239         else
240                 return -EINVAL;
241
242         return 0;
243 }
244
245 const char *bus_message_type_to_string(uint8_t u) {
246         if (u == SD_BUS_MESSAGE_TYPE_SIGNAL)
247                 return "signal";
248         else if (u == SD_BUS_MESSAGE_TYPE_METHOD_CALL)
249                 return "method_call";
250         else if (u == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
251                 return "error";
252         else if (u == SD_BUS_MESSAGE_TYPE_METHOD_RETURN)
253                  return "method_return";
254         else
255                 return NULL;
256 }