]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/parse-util.c
tty-ask-password: Split out password sending
[thirdparty/systemd.git] / src / basic / parse-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 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 <errno.h>
23 #include <inttypes.h>
24 #include <locale.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <xlocale.h>
29
30 #include "alloc-util.h"
31 #include "extract-word.h"
32 #include "macro.h"
33 #include "parse-util.h"
34 #include "string-util.h"
35
36 int parse_boolean(const char *v) {
37 assert(v);
38
39 if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
40 return 1;
41 else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
42 return 0;
43
44 return -EINVAL;
45 }
46
47 int parse_pid(const char *s, pid_t* ret_pid) {
48 unsigned long ul = 0;
49 pid_t pid;
50 int r;
51
52 assert(s);
53 assert(ret_pid);
54
55 r = safe_atolu(s, &ul);
56 if (r < 0)
57 return r;
58
59 pid = (pid_t) ul;
60
61 if ((unsigned long) pid != ul)
62 return -ERANGE;
63
64 if (pid <= 0)
65 return -ERANGE;
66
67 *ret_pid = pid;
68 return 0;
69 }
70
71 int parse_mode(const char *s, mode_t *ret) {
72 char *x;
73 long l;
74
75 assert(s);
76 assert(ret);
77
78 s += strspn(s, WHITESPACE);
79 if (s[0] == '-')
80 return -ERANGE;
81
82 errno = 0;
83 l = strtol(s, &x, 8);
84 if (errno > 0)
85 return -errno;
86 if (!x || x == s || *x)
87 return -EINVAL;
88 if (l < 0 || l > 07777)
89 return -ERANGE;
90
91 *ret = (mode_t) l;
92 return 0;
93 }
94
95 int parse_ifindex(const char *s, int *ret) {
96 int ifi, r;
97
98 r = safe_atoi(s, &ifi);
99 if (r < 0)
100 return r;
101 if (ifi <= 0)
102 return -EINVAL;
103
104 *ret = ifi;
105 return 0;
106 }
107
108 int parse_size(const char *t, uint64_t base, uint64_t *size) {
109
110 /* Soo, sometimes we want to parse IEC binary suffixes, and
111 * sometimes SI decimal suffixes. This function can parse
112 * both. Which one is the right way depends on the
113 * context. Wikipedia suggests that SI is customary for
114 * hardware metrics and network speeds, while IEC is
115 * customary for most data sizes used by software and volatile
116 * (RAM) memory. Hence be careful which one you pick!
117 *
118 * In either case we use just K, M, G as suffix, and not Ki,
119 * Mi, Gi or so (as IEC would suggest). That's because that's
120 * frickin' ugly. But this means you really need to make sure
121 * to document which base you are parsing when you use this
122 * call. */
123
124 struct table {
125 const char *suffix;
126 unsigned long long factor;
127 };
128
129 static const struct table iec[] = {
130 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
131 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
132 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
133 { "G", 1024ULL*1024ULL*1024ULL },
134 { "M", 1024ULL*1024ULL },
135 { "K", 1024ULL },
136 { "B", 1ULL },
137 { "", 1ULL },
138 };
139
140 static const struct table si[] = {
141 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
142 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
143 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
144 { "G", 1000ULL*1000ULL*1000ULL },
145 { "M", 1000ULL*1000ULL },
146 { "K", 1000ULL },
147 { "B", 1ULL },
148 { "", 1ULL },
149 };
150
151 const struct table *table;
152 const char *p;
153 unsigned long long r = 0;
154 unsigned n_entries, start_pos = 0;
155
156 assert(t);
157 assert(base == 1000 || base == 1024);
158 assert(size);
159
160 if (base == 1000) {
161 table = si;
162 n_entries = ELEMENTSOF(si);
163 } else {
164 table = iec;
165 n_entries = ELEMENTSOF(iec);
166 }
167
168 p = t;
169 do {
170 unsigned long long l, tmp;
171 double frac = 0;
172 char *e;
173 unsigned i;
174
175 p += strspn(p, WHITESPACE);
176
177 errno = 0;
178 l = strtoull(p, &e, 10);
179 if (errno > 0)
180 return -errno;
181 if (e == p)
182 return -EINVAL;
183 if (*p == '-')
184 return -ERANGE;
185
186 if (*e == '.') {
187 e++;
188
189 /* strtoull() itself would accept space/+/- */
190 if (*e >= '0' && *e <= '9') {
191 unsigned long long l2;
192 char *e2;
193
194 l2 = strtoull(e, &e2, 10);
195 if (errno > 0)
196 return -errno;
197
198 /* Ignore failure. E.g. 10.M is valid */
199 frac = l2;
200 for (; e < e2; e++)
201 frac /= 10;
202 }
203 }
204
205 e += strspn(e, WHITESPACE);
206
207 for (i = start_pos; i < n_entries; i++)
208 if (startswith(e, table[i].suffix))
209 break;
210
211 if (i >= n_entries)
212 return -EINVAL;
213
214 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
215 return -ERANGE;
216
217 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
218 if (tmp > ULLONG_MAX - r)
219 return -ERANGE;
220
221 r += tmp;
222 if ((unsigned long long) (uint64_t) r != r)
223 return -ERANGE;
224
225 p = e + strlen(table[i].suffix);
226
227 start_pos = i + 1;
228
229 } while (*p);
230
231 *size = r;
232
233 return 0;
234 }
235
236 int parse_range(const char *t, unsigned *lower, unsigned *upper) {
237 _cleanup_free_ char *word = NULL;
238 unsigned l, u;
239 int r;
240
241 assert(lower);
242 assert(upper);
243
244 /* Extract the lower bound. */
245 r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
246 if (r < 0)
247 return r;
248 if (r == 0)
249 return -EINVAL;
250
251 r = safe_atou(word, &l);
252 if (r < 0)
253 return r;
254
255 /* Check for the upper bound and extract it if needed */
256 if (!t)
257 /* Single number with no dashes. */
258 u = l;
259 else if (!*t)
260 /* Trailing dash is an error. */
261 return -EINVAL;
262 else {
263 r = safe_atou(t, &u);
264 if (r < 0)
265 return r;
266 }
267
268 *lower = l;
269 *upper = u;
270 return 0;
271 }
272
273 char *format_bytes(char *buf, size_t l, uint64_t t) {
274 unsigned i;
275
276 /* This only does IEC units so far */
277
278 static const struct {
279 const char *suffix;
280 uint64_t factor;
281 } table[] = {
282 { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
283 { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
284 { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
285 { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
286 { "M", UINT64_C(1024)*UINT64_C(1024) },
287 { "K", UINT64_C(1024) },
288 };
289
290 if (t == (uint64_t) -1)
291 return NULL;
292
293 for (i = 0; i < ELEMENTSOF(table); i++) {
294
295 if (t >= table[i].factor) {
296 snprintf(buf, l,
297 "%" PRIu64 ".%" PRIu64 "%s",
298 t / table[i].factor,
299 ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
300 table[i].suffix);
301
302 goto finish;
303 }
304 }
305
306 snprintf(buf, l, "%" PRIu64 "B", t);
307
308 finish:
309 buf[l-1] = 0;
310 return buf;
311
312 }
313
314 int safe_atou(const char *s, unsigned *ret_u) {
315 char *x = NULL;
316 unsigned long l;
317
318 assert(s);
319 assert(ret_u);
320
321 /* strtoul() is happy to parse negative values, and silently
322 * converts them to unsigned values without generating an
323 * error. We want a clean error, hence let's look for the "-"
324 * prefix on our own, and generate an error. But let's do so
325 * only after strtoul() validated that the string is clean
326 * otherwise, so that we return EINVAL preferably over
327 * ERANGE. */
328
329 s += strspn(s, WHITESPACE);
330
331 errno = 0;
332 l = strtoul(s, &x, 0);
333 if (errno > 0)
334 return -errno;
335 if (!x || x == s || *x)
336 return -EINVAL;
337 if (s[0] == '-')
338 return -ERANGE;
339 if ((unsigned long) (unsigned) l != l)
340 return -ERANGE;
341
342 *ret_u = (unsigned) l;
343 return 0;
344 }
345
346 int safe_atoi(const char *s, int *ret_i) {
347 char *x = NULL;
348 long l;
349
350 assert(s);
351 assert(ret_i);
352
353 errno = 0;
354 l = strtol(s, &x, 0);
355 if (errno > 0)
356 return -errno;
357 if (!x || x == s || *x)
358 return -EINVAL;
359 if ((long) (int) l != l)
360 return -ERANGE;
361
362 *ret_i = (int) l;
363 return 0;
364 }
365
366 int safe_atollu(const char *s, long long unsigned *ret_llu) {
367 char *x = NULL;
368 unsigned long long l;
369
370 assert(s);
371 assert(ret_llu);
372
373 s += strspn(s, WHITESPACE);
374
375 errno = 0;
376 l = strtoull(s, &x, 0);
377 if (errno > 0)
378 return -errno;
379 if (!x || x == s || *x)
380 return -EINVAL;
381 if (*s == '-')
382 return -ERANGE;
383
384 *ret_llu = l;
385 return 0;
386 }
387
388 int safe_atolli(const char *s, long long int *ret_lli) {
389 char *x = NULL;
390 long long l;
391
392 assert(s);
393 assert(ret_lli);
394
395 errno = 0;
396 l = strtoll(s, &x, 0);
397 if (errno > 0)
398 return -errno;
399 if (!x || x == s || *x)
400 return -EINVAL;
401
402 *ret_lli = l;
403 return 0;
404 }
405
406 int safe_atou8(const char *s, uint8_t *ret) {
407 char *x = NULL;
408 unsigned long l;
409
410 assert(s);
411 assert(ret);
412
413 s += strspn(s, WHITESPACE);
414
415 errno = 0;
416 l = strtoul(s, &x, 0);
417 if (errno > 0)
418 return -errno;
419 if (!x || x == s || *x)
420 return -EINVAL;
421 if (s[0] == '-')
422 return -ERANGE;
423 if ((unsigned long) (uint8_t) l != l)
424 return -ERANGE;
425
426 *ret = (uint8_t) l;
427 return 0;
428 }
429
430 int safe_atou16(const char *s, uint16_t *ret) {
431 char *x = NULL;
432 unsigned long l;
433
434 assert(s);
435 assert(ret);
436
437 s += strspn(s, WHITESPACE);
438
439 errno = 0;
440 l = strtoul(s, &x, 0);
441 if (errno > 0)
442 return -errno;
443 if (!x || x == s || *x)
444 return -EINVAL;
445 if (s[0] == '-')
446 return -ERANGE;
447 if ((unsigned long) (uint16_t) l != l)
448 return -ERANGE;
449
450 *ret = (uint16_t) l;
451 return 0;
452 }
453
454 int safe_atoi16(const char *s, int16_t *ret) {
455 char *x = NULL;
456 long l;
457
458 assert(s);
459 assert(ret);
460
461 errno = 0;
462 l = strtol(s, &x, 0);
463 if (errno > 0)
464 return -errno;
465 if (!x || x == s || *x)
466 return -EINVAL;
467 if ((long) (int16_t) l != l)
468 return -ERANGE;
469
470 *ret = (int16_t) l;
471 return 0;
472 }
473
474 int safe_atod(const char *s, double *ret_d) {
475 char *x = NULL;
476 double d = 0;
477 locale_t loc;
478
479 assert(s);
480 assert(ret_d);
481
482 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
483 if (loc == (locale_t) 0)
484 return -errno;
485
486 errno = 0;
487 d = strtod_l(s, &x, loc);
488 if (errno > 0) {
489 freelocale(loc);
490 return -errno;
491 }
492 if (!x || x == s || *x) {
493 freelocale(loc);
494 return -EINVAL;
495 }
496
497 freelocale(loc);
498 *ret_d = (double) d;
499 return 0;
500 }
501
502 int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
503 size_t i;
504 unsigned val = 0;
505 const char *s;
506
507 s = *p;
508
509 /* accept any number of digits, strtoull is limted to 19 */
510 for(i=0; i < digits; i++,s++) {
511 if (*s < '0' || *s > '9') {
512 if (i == 0)
513 return -EINVAL;
514
515 /* too few digits, pad with 0 */
516 for (; i < digits; i++)
517 val *= 10;
518
519 break;
520 }
521
522 val *= 10;
523 val += *s - '0';
524 }
525
526 /* maybe round up */
527 if (*s >= '5' && *s <= '9')
528 val++;
529
530 s += strspn(s, DIGITS);
531
532 *p = s;
533 *res = val;
534
535 return 0;
536 }