The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
print.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Functions to produce and parse the FreeRADIUS presentation format
18 *
19 * @file src/lib/util/print.c
20 *
21 * @copyright 2000,2006 The FreeRADIUS server project
22 */
23RCSID("$Id: e9fd3b0645e98181df408fd187d6e3ec460cfeab $")
24
25#include <freeradius-devel/util/debug.h>
26#include <freeradius-devel/util/base16.h>
27#include <freeradius-devel/util/pair.h>
28
29
30/** Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8
31 *
32 * @param[in] str input string.
33 * @param[in] inlen length of input string. May be -1 if str
34 * is \0 terminated.
35 * @return
36 * - 0 if the character is invalid.
37 * - >0 the number of bytes the character consists of.
38 */
39inline size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
40{
41 if (inlen == 0) return 0;
42
43 if (inlen < 0) inlen = 4; /* longest char */
44
45 if (*str <= 0x7f) return 1; /* 1 */
46
47 if (*str <= 0xc1) return 0;
48
49 if (inlen < 2) return 0;
50
51 if ((str[0] >= 0xc2) && /* 2 */
52 (str[0] <= 0xdf) &&
53 (str[1] >= 0x80) &&
54 (str[1] <= 0xbf)) {
55 return 2;
56 }
57
58 if (inlen < 3) return 0;
59
60 if ((str[0] == 0xe0) && /* 3 */
61 (str[1] >= 0xa0) &&
62 (str[1] <= 0xbf) &&
63 (str[2] >= 0x80) &&
64 (str[2] <= 0xbf)) {
65 return 3;
66 }
67
68 if ((str[0] >= 0xe1) && /* 4a */
69 (str[0] <= 0xec) &&
70 (str[1] >= 0x80) &&
71 (str[1] <= 0xbf) &&
72 (str[2] >= 0x80) &&
73 (str[2] <= 0xbf)) {
74 return 3;
75 }
76
77 if ((str[0] >= 0xee) && /* 4b */
78 (str[0] <= 0xef) &&
79 (str[1] >= 0x80) &&
80 (str[1] <= 0xbf) &&
81 (str[2] >= 0x80) &&
82 (str[2] <= 0xbf)) {
83 return 3;
84 }
85
86 if ((str[0] == 0xed) && /* 5 */
87 (str[1] >= 0x80) &&
88 (str[1] <= 0x9f) &&
89 (str[2] >= 0x80) &&
90 (str[2] <= 0xbf)) {
91 return 3;
92 }
93
94 if (inlen < 4) return 0;
95
96 if ((str[0] == 0xf0) && /* 6 */
97 (str[1] >= 0x90) &&
98 (str[1] <= 0xbf) &&
99 (str[2] >= 0x80) &&
100 (str[2] <= 0xbf) &&
101 (str[3] >= 0x80) &&
102 (str[3] <= 0xbf)) {
103 return 4;
104 }
105
106 if ((str[0] >= 0xf1) && /* 6 */
107 (str[0] <= 0xf3) &&
108 (str[1] >= 0x80) &&
109 (str[1] <= 0xbf) &&
110 (str[2] >= 0x80) &&
111 (str[2] <= 0xbf) &&
112 (str[3] >= 0x80) &&
113 (str[3] <= 0xbf)) {
114 return 4;
115 }
116
117
118 if ((str[0] == 0xf4) && /* 7 */
119 (str[1] >= 0x80) &&
120 (str[1] <= 0x8f) &&
121 (str[2] >= 0x80) &&
122 (str[2] <= 0xbf) &&
123 (str[3] >= 0x80) &&
124 (str[3] <= 0xbf)) {
125 return 4;
126 }
127
128 /*
129 * Invalid UTF-8 Character
130 */
131 return 0;
132}
133
134/** Validate a complete UTF8 string
135 *
136 * @param[in] str input string.
137 * @param[in] inlen length of input string. May be -1 if str
138 * is \0 terminated.
139 * @return The number of bytes validated. If ret == inlen the entire
140 * string is valid. Else ret gives the negative offset at
141 * which the first invalid byte sequence was found.
142 */
144{
145 uint8_t const *p, *end;
146 size_t len;
147
148 len = inlen < 0 ? strlen((char const *)str) : (size_t) inlen;
149
150 p = str;
151 end = p + len;
152
153 do {
154 size_t clen;
155
156 clen = fr_utf8_char(p, end - p);
157 if (clen == 0) return p - end;
158 p += clen;
159 } while (p < end);
160
161 return inlen;
162}
163
164/** Return a pointer to the first UTF8 char in a string.
165 *
166 * @param[out] out_chr_len Where to write the length of the multibyte char passed in chr (may be NULL).
167 * @param[in] str Haystack.
168 * @param[in] inlen Length of string (in bytes). Pass -1 to determine the length of the string.
169 * @param[in] chr Multibyte needle.
170 * @return
171 * - Position of chr in str.
172 * - NULL if not found.
173 */
174char const *fr_utf8_strchr(int *out_chr_len, char const *str, ssize_t inlen, char const *chr)
175{
176 char const *p = str, *end;
177 int needle_len;
178
179 if (inlen < 0) inlen = strlen(str);
180
181 end = str + inlen;
182
183 /*
184 * Figure out how big the multibyte sequence
185 * we're looking for is.
186 */
187 needle_len = fr_utf8_char((uint8_t const *)chr, -1);
188 if (needle_len == 0) needle_len = 1; /* Invalid UTF8 sequence - ignore - needle is one byte */
189 if (out_chr_len) *out_chr_len = needle_len;
190
191 /*
192 * Loop over the input sequence, advancing
193 * UTF8 sequence by utf8 seqnce.
194 */
195 while (p < end) {
196 int schr_len;
197
198 schr_len = fr_utf8_char((uint8_t const *)p, end - p);
199 if (schr_len == 0) schr_len = 1; /* Invalid UTF8 sequence - ignore - advance by 1 */
200 if (schr_len != needle_len) goto next;
201
202 /*
203 * See if this matches out multibyte needle
204 */
205 if (memcmp(p, chr, schr_len) == 0) return p;
206 next:
207 p += schr_len;
208 }
209
210 return NULL;
211}
212
213/** Escape any non printable or non-UTF8 characters in the input string
214 *
215 * @note Return value should be checked with is_truncated
216 * @note Will always \0 terminate unless outlen == 0.
217 *
218 * @param[out] out where to write the escaped string.
219 * @param[out] outlen the length of the buffer pointed to by out.
220 * @param[in] in string to escape.
221 * @param[in] inlen length of string to escape (lets us deal with embedded NULs)
222 * @param[in] quote the quotation character
223 * @return
224 * - The number of bytes written to the out buffer.
225 * - A number >= outlen if truncation has occurred.
226 */
227size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
228{
229 uint8_t const *p = (uint8_t const *) in;
230 size_t utf8;
231 size_t used;
232 size_t freespace;
233
234 /* No input, so no output... */
235 if (!in) {
236 if (out && outlen) *out = '\0';
237 return 0;
238 }
239
240 /* Figure out the length of the input string */
241 if (inlen < 0) inlen = strlen(in);
242
243 /*
244 * No quotation character, just use memcpy, ensuring we
245 * don't overflow the output buffer.
246 */
247 if (!quote) {
248 if (!out) return inlen;
249
250 if ((size_t)inlen >= outlen) {
251 memcpy(out, in, outlen - 1);
252 out[outlen - 1] = '\0';
253 } else {
254 memcpy(out, in, inlen);
255 out[inlen] = '\0';
256 }
257
258 return inlen;
259 }
260
261 /*
262 * Check the output buffer and length. Zero both of them
263 * out if either are zero.
264 */
265 freespace = outlen;
266 if (freespace == 0) out = NULL;
267 if (!out) freespace = 0;
268
269 used = 0;
270
271 while (inlen > 0) {
272 int sp = 0;
273
274 /*
275 * Always escape the quotation character.
276 */
277 if (*p == quote) {
278 sp = quote;
279 goto do_escape;
280 }
281
282 /*
283 * Escape the backslash ONLY for single quoted strings.
284 */
285 if (quote == '\'') {
286 if (*p == '\\') {
287 sp = '\\';
288 }
289 goto do_escape;
290 }
291
292 /*
293 * Try to convert 0x0a --> \r, etc.
294 * Backslashes get handled specially.
295 */
296 switch (*p) {
297 case '\r':
298 sp = 'r';
299 break;
300
301 case '\n':
302 sp = 'n';
303 break;
304
305 case '\t':
306 sp = 't';
307 break;
308
309 case '\\':
310 sp = '\\';
311 break;
312
313 default:
314 sp = '\0';
315 break;
316 } /* escape the character at *p */
317
318 do_escape:
319 if (sp) {
320 if ((freespace > 0) && (freespace <= 2)) {
321 if (out) out[used] = '\0';
322 out = NULL;
323 freespace = 0;
324
325 } else if (freespace > 2) { /* room for char AND trailing zero */
326 if (out) {
327 out[used] = '\\';
328 out[used + 1] = sp;
329 }
330 freespace -= 2;
331 }
332
333 used += 2;
334 p++;
335 inlen--;
336 continue;
337 }
338
339 /*
340 * All strings are UTF-8 clean.
341 */
342 utf8 = fr_utf8_char(p, inlen);
343
344 /*
345 * If we have an invalid UTF-8 character, it gets
346 * copied over as a 1-byte character for single
347 * quoted strings. Which means that the output
348 * isn't strictly UTF-8, but oh well...
349 *
350 * For double quoted strints, the invalid
351 * characters get escaped as octal encodings.
352 */
353 if (utf8 == 0) {
354 if (quote == '\'') {
355 utf8 = 1;
356
357 } else {
358 if ((freespace > 0) && (freespace <= 4)) {
359 if (out) out[used] = '\0';
360 out = NULL;
361 freespace = 0;
362
363 } else if (freespace > 4) { /* room for char AND trailing zero */
364 if (out) snprintf(out + used, freespace, "\\%03o", *p);
365 freespace -= 4;
366 }
367
368 used += 4;
369 p++;
370 inlen--;
371 continue;
372 }
373 }
374
375 if ((freespace > 0) && (freespace <= utf8)) {
376 if (out) out[used] = '\0';
377 out = NULL;
378 freespace = 0;
379
380 } else if (freespace > utf8) { /* room for char AND trailing zero */
381 if (out) memcpy(out + used, p, utf8);
382 freespace -= utf8;
383 }
384
385 used += utf8;
386 p += utf8;
387 inlen -= utf8;
388 }
389
390 /*
391 * Ensure that the output buffer is always zero terminated.
392 */
393 if (out && freespace) out[used] = '\0';
394
395 return used;
396}
397
398/** Find the length of the buffer required to fully escape a string with fr_prints
399 *
400 * Were assuming here that's it's cheaper to figure out the length and do one
401 * alloc than repeatedly expand the buffer when we find extra chars which need
402 * to be added.
403 *
404 * @param in string to calculate the escaped length for.
405 * @param inlen length of the input string, if < 0 strlen will be used to check the length.
406 * @param[in] quote the quotation character.
407 * @return the size of buffer required to hold the escaped string including the NUL byte.
408 */
409size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
410{
411 return fr_snprint(NULL, 0, in, inlen, quote) + 1;
412}
413
414/** Escape string that may contain binary data, and write it to a new buffer
415 *
416 * This is useful in situations where we expect printable strings as input,
417 * but under some conditions may get binary data. A good example is libldap
418 * and the arrays of struct berval ldap_get_values_len returns.
419 *
420 * @param[in] ctx To allocate new buffer in.
421 * @param[in] in String to escape.
422 * @param[in] inlen Length of string. Should be >= 0 if the data may contain
423 * embedded \0s. Must be >= 0 if data may not be \0 terminated.
424 * If < 0 inlen will be calculated using strlen.
425 * @param[in] quote the quotation character.
426 * @return new buffer holding the escaped string.
427 */
428char *fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
429{
430 size_t len, ret;
431 char *out;
432
433 len = fr_snprint_len(in, inlen, quote);
434
435 out = talloc_array(ctx, char, len);
436 ret = fr_snprint(out, len, in, inlen, quote);
437 /*
438 * This is a fatal error, but fr_cond_assert is the strongest
439 * assert we're allowed to use in library functions.
440 */
441 if (!fr_cond_assert(ret == (len - 1))) {
443 return NULL;
444 }
445
446 return out;
447}
448
449DIAG_OFF(format-nonliteral)
450/** Special version of vasprintf which implements custom format specifiers
451 *
452 * @todo Do something sensible with 'n$', though it's probably not actually used
453 * anywhere in our code base.
454 *
455 * - %pV prints a value box as a string.
456 * - %pM prints a list of value boxes, concatenating them.
457 * - %pH prints a value box as a hex string.
458 * - %pP prints a fr_pair_t.
459 *
460 * This breaks strict compatibility with printf but allows us to continue using
461 * the static format string and argument type validation.
462 *
463 * This same idea is used in Linux for the printk function.
464 *
465 * @param[in] ctx to allocate buffer in.
466 * @param[in] fmt string.
467 * @param[in] ap variadic argument list.
468 * @param[in] suppress_secrets as described
469 * @return
470 * - The result of string interpolation.
471 * - NULL if OOM.
472 */
473static char *fr_vasprintf_internal(TALLOC_CTX *ctx, char const *fmt, va_list ap, bool suppress_secrets)
474{
475 char const *p = fmt, *end = p + strlen(fmt), *fmt_p = p, *fmt_q = p;
476 char *out = NULL, *out_tmp;
477 va_list ap_p, ap_q;
478 char *subst;
479
480 out = talloc_strdup(ctx, "");
481 va_copy(ap_p, ap);
482 va_copy(ap_q, ap_p);
483
484 do {
485 char const *q;
486 char len[2] = { '\0', '\0' };
487
488 subst = NULL;
489
490 if ((*p != '%') || (*++p == '%')) {
491 fmt_q = p + 1;
492 continue; /* literal char */
493 }
494
495 /*
496 * Check for parameter field
497 */
498 for (q = p; isdigit((uint8_t) *q); q++);
499 if ((q != p) && (*q == '$')) {
500 p = q + 1;
501 }
502
503 /*
504 * Check for flags
505 */
506 do {
507 switch (*p) {
508 case '-':
509 continue;
510
511 case '+':
512 continue;
513
514 case ' ':
515 continue;
516
517 case '0':
518 continue;
519
520 case '#':
521 continue;
522
523 default:
524 goto done_flags;
525 }
526 } while (++p < end);
527 done_flags:
528
529 /*
530 * Check for width field. First for strings, and
531 * then for other parameters.
532 */
533 if ((*p == '.') && (*(p + 1) == '*') && (*(p + 2) == 's')) {
534 (void) va_arg(ap_q, int);
535 p += 2;
536 } else if (*p == '*') {
537 (void) va_arg(ap_q, int);
538 p++;
539 } else {
540 for (q = p; isdigit((uint8_t) *q); q++);
541 p = q;
542 }
543
544 /*
545 * Check for precision field
546 */
547 if (*p == '.') {
548 char *r;
549
550 p++;
551 (void) strtoul(p, &r, 10);
552 p = r;
553 }
554
555 /*
556 * Length modifiers
557 */
558 switch (*p) {
559 case 'h':
560 case 'l':
561 len[0] = *p++;
562 if ((*p == 'h') || (*p == 'l')) len[1] = *p++;
563 break;
564
565 case 'L':
566 case 'z':
567 case 'j':
568 case 't':
569 len[0] = *p++;
570 break;
571 }
572
573 /*
574 * Types
575 */
576 switch (*p) {
577 case 'i': /* int */
578 case 'd': /* int */
579 case 'u': /* unsigned int */
580 case 'x': /* unsigned int */
581 case 'X': /* unsigned int */
582 case 'o': /* unsigned int */
583 switch (len[0]) {
584 case 'h':
585 if (len[1] == 'h') { /* char (promoted to int) */
586 (void) va_arg(ap_q, int);
587 } else {
588 (void) va_arg(ap_q, int); /* short (promoted to int) */
589 }
590 break;
591
592 case 'l':
593 if ((*p == 'i') || (*p == 'd')) {
594 if (len[1] == 'l') {
595 (void) va_arg(ap_q, long); /* long */
596 } else {
597 (void) va_arg(ap_q, long long); /* long long */
598 }
599 } else {
600 if (len[1] == 'l') {
601 (void) va_arg(ap_q, unsigned long); /* unsigned long */
602 } else {
603 (void) va_arg(ap_q, unsigned long long);/* unsigned long long */
604 }
605 }
606 break;
607
608 case 'z':
609 (void) va_arg(ap_q, size_t); /* size_t */
610 break;
611
612 case 'j':
613 (void) va_arg(ap_q, intmax_t); /* intmax_t */
614 break;
615
616 case 't':
617 (void) va_arg(ap_q, ptrdiff_t); /* ptrdiff_t */
618 break;
619
620 case '\0': /* no length modifier */
621 if ((*p == 'i') || (*p == 'd')) {
622 (void) va_arg(ap_q, int); /* int */
623 } else {
624 (void) va_arg(ap_q, unsigned int); /* unsigned int */
625 }
626 }
627 break;
628
629 case 'f': /* double */
630 case 'F': /* double */
631 case 'e': /* double */
632 case 'E': /* double */
633 case 'g': /* double */
634 case 'G': /* double */
635 case 'a': /* double */
636 case 'A': /* double */
637 switch (len[0]) {
638 case 'L':
639 (void) va_arg(ap_q, long double); /* long double */
640 break;
641
642 case 'l': /* does nothing */
643 default: /* no length modifier */
644 (void) va_arg(ap_q, double); /* double */
645 }
646 break;
647
648 case 's':
649 (void) va_arg(ap_q, char *); /* char * */
650 break;
651
652 case 'c':
653 (void) va_arg(ap_q, int); /* char (promoted to int) */
654 break;
655
656 case 'p':
657 /*
658 * subst types
659 */
660 switch (*(p + 1)) {
661 case 'V':
662 case 'R':
663 {
664 fr_value_box_t const *in = va_arg(ap_q, fr_value_box_t const *);
665 fr_sbuff_escape_rules_t const *e_rules = NULL;
666
667 /*
668 * Value boxes get escaped as double-quoted strings, unless the value-box
669 * in question is secret, AND we've been asked to hide secrets.
670 *
671 * Note that the secret_rules only hides secrets of data type "string",
672 * which should be good enough for most purposes.
673 */
674 if (*(p + 1) == 'V') {
675 e_rules = &fr_value_escape_double;
676 }
677
678 /*
679 * Allocations that are not part of the output
680 * string need to occur in the NULL ctx so we don't fragment
681 * any pool associated with it.
682 */
683 if (unlikely(in && in->secret && suppress_secrets)) {
684 subst = talloc_typed_strdup(NULL, "<<< secret >>>");
685
686 } else if (in) {
687 fr_value_box_aprint(NULL, &subst, in, e_rules);
688 } else {
689 subst = talloc_typed_strdup(NULL, "(null)");
690 }
691
692 do_splice:
693 if (!subst) goto oom;
694
695 p++;
696
697 /*
698 * Pass part of a format string to printf
699 */
700 if (fmt_q != fmt_p) {
701 char *sub_fmt;
702
703 sub_fmt = talloc_strndup(NULL, fmt_p, fmt_q - fmt_p);
704 out_tmp = talloc_vasprintf_append_buffer(out, sub_fmt, ap_p);
705 talloc_free(sub_fmt);
706 if (!out_tmp) {
707 oom:
708 fr_strerror_const("Out of memory");
710 TALLOC_FREE(subst);
711 va_end(ap_p);
712 va_end(ap_q);
713 return NULL;
714 }
715 out = out_tmp;
716
717 out_tmp = talloc_strdup_append_buffer(out, subst);
718 if (!out_tmp) goto oom;
719 TALLOC_FREE(subst);
720 out = out_tmp;
721
722 va_end(ap_p); /* one time use only */
723 } else {
724 out_tmp = talloc_strdup_append_buffer(out, subst);
725 if (!out_tmp) goto oom;
726 TALLOC_FREE(subst);
727 out = out_tmp;
728 }
729
730 va_copy(ap_p, ap_q); /* already advanced to the next argument */
731
732 fmt_p = p + 1;
733 }
734 break;
735
736 case 'H':
737 {
738 fr_value_box_t const *in = va_arg(ap_q, fr_value_box_t const *);
739
740 if (!in) {
741 subst = talloc_strdup(NULL, "(null)");
742 goto do_splice;
743 }
744
745 switch (in->type) {
746 case FR_TYPE_OCTETS:
747 if (in->vb_octets) {
748 fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP(in->vb_octets, in->vb_length));
749 } else {
750 subst = talloc_strdup(NULL, "");
751 }
752 break;
753
754 case FR_TYPE_STRING:
755 fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP((uint8_t const *)in->vb_strvalue, in->vb_length));
756 break;
757
758 default:
759 {
760 fr_value_box_t dst;
761
762 /*
763 * Convert the boxed value into a octets buffer
764 */
765 if (fr_value_box_cast(NULL, &dst, FR_TYPE_OCTETS, NULL, in) < 0) {
766 subst = talloc_strdup(NULL, fr_strerror()); /* splice in the error */
767 if (!subst) goto oom;
768 }
769
770 fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP((uint8_t const *)dst.vb_octets, dst.vb_length));
771 fr_value_box_clear(&dst);
772 break;
773 }
774 }
775 }
776 goto do_splice;
777
778 case 'M':
779 {
780 fr_value_box_list_t const *in = va_arg(ap_q, fr_value_box_list_t const *);
781
782 if (!in) {
783 subst = talloc_strdup(NULL, "(null)");
784 goto do_splice;
785 }
786
787 if (suppress_secrets) {
789 } else {
791 }
792 }
793 goto do_splice;
794
795 case 'P':
796 {
797 fr_pair_t const *in = va_arg(ap_q, fr_pair_t const *);
798
799 if (!in) {
800 subst = talloc_strdup(NULL, "(null)");
801 goto do_splice;
802 }
803
805
806 if (unlikely(in && in->data.secret && suppress_secrets)) {
807 fr_pair_aprint_secure(NULL, &subst, NULL, in);
808 } else {
809 fr_pair_aprint(NULL, &subst, NULL, in);
810 }
811 }
812 goto do_splice;
813
814 default:
815 (void) va_arg(ap_q, void *); /* void * */
816 }
817 break;
818
819 case 'n':
820 (void) va_arg(ap_q, int *); /* int * */
821 break;
822
823 default:
824 break;
825 }
826 fmt_q = p + 1;
827 } while (++p < end);
828
829 /*
830 * Print out the rest of the format string.
831 */
832 if (*fmt_p) {
833 out_tmp = talloc_vasprintf_append_buffer(out, fmt_p, ap_p);
834 if (!out_tmp) goto oom;
835 out = out_tmp;
836 }
837
838 va_end(ap_p);
839 va_end(ap_q);
840
841 /*
842 * One of the above talloc calls sets the type to
843 * be the string. We correct this here so we
844 * don't trigger talloc_aborts later...
845 */
846 talloc_set_type(out, char);
847
848 return out;
849}
850
851char *fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
852{
853 return fr_vasprintf_internal(ctx, fmt, ap, false);
854}
855
856char *fr_vasprintf_secure(TALLOC_CTX *ctx, char const *fmt, va_list ap)
857{
858 return fr_vasprintf_internal(ctx, fmt, ap, true);
859}
860
861
862DIAG_ON(format-nonliteral)
863
864/** Special version of asprintf which implements custom format specifiers
865 *
866 * @copybrief fr_vasprintf
867 *
868 * @param[in] ctx to allocate buffer in.
869 * @param[in] fmt string.
870 * @param[in] ... variadic argument list.
871 * @return
872 * - The result of string interpolation.
873 */
874char *fr_asprintf(TALLOC_CTX *ctx, char const *fmt, ...)
875{
876 va_list ap;
877 char *ret;
878
879 va_start(ap, fmt);
880 ret = fr_vasprintf(ctx, fmt, ap);
881 va_end(ap);
882
883 return ret;
884}
885
886/** Special version of fprintf which implements custom format specifiers
887 *
888 * @copybrief fr_vasprintf
889 *
890 * @param[in] fp to write the result of fmt string.
891 * @param[in] fmt string.
892 * @param[in] ... variadic argument list.
893 * @return
894 * - On success, the number of bytes written is returned (zero indicates nothing was written).
895 * - On error, -1 is returned, and errno is set appropriately
896 */
897ssize_t fr_fprintf(FILE *fp, char const *fmt, ...)
898{
899 va_list ap;
900 char *buf;
901 int ret;
902
903 if (!fp) {
904 fr_strerror_const("Invalid 'fp'");
905 return -1;
906 }
907
908 va_start(ap, fmt);
909 buf = fr_vasprintf(NULL, fmt, ap);
910 va_end(ap);
911
912 ret = fputs(buf, fp);
913
914 TALLOC_FREE(buf);
915
916 return ret;
917}
va_end(args)
static int const char * fmt
Definition acutest.h:573
va_start(args, fmt)
static fr_slen_t fr_base16_aencode(TALLOC_CTX *ctx, char **out, fr_dbuff_t *in)
Convert binary data to a hex string, allocating the output buffer.
Definition base16.h:71
#define RCSID(id)
Definition build.h:483
#define DIAG_ON(_x)
Definition build.h:458
#define unlikely(_x)
Definition build.h:381
#define DIAG_OFF(_x)
Definition build.h:457
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
static fr_slen_t in
Definition dict.h:824
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
unsigned char uint8_t
ssize_t fr_slen_t
unsigned long int size_t
static size_t used
ssize_t fr_fprintf(FILE *fp, char const *fmt,...)
Special version of fprintf which implements custom format specifiers.
Definition print.c:897
size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
Escape any non printable or non-UTF8 characters in the input string.
Definition print.c:227
char * fr_vasprintf_secure(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition print.c:856
char const * fr_utf8_strchr(int *out_chr_len, char const *str, ssize_t inlen, char const *chr)
Return a pointer to the first UTF8 char in a string.
Definition print.c:174
fr_slen_t fr_utf8_str(uint8_t const *str, ssize_t inlen)
Validate a complete UTF8 string.
Definition print.c:143
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition print.c:39
size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
Find the length of the buffer required to fully escape a string with fr_prints.
Definition print.c:409
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
Definition print.c:428
static char * fr_vasprintf_internal(TALLOC_CTX *ctx, char const *fmt, va_list ap, bool suppress_secrets)
Special version of vasprintf which implements custom format specifiers.
Definition print.c:473
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition print.c:851
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition print.c:874
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:445
static fr_slen_t fr_pair_aprint(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print
#define PAIR_VERIFY(_x)
Definition pair.h:191
static fr_slen_t static vp fr_slen_t fr_pair_aprint_secure(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print_secure
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
#define fr_strerror_const(_msg)
Definition strerror.h:223
fr_sbuff_escape_rules_t fr_value_escape_double
Definition value.c:350
char * fr_value_box_list_aprint_secure(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together hiding "secret" values.
Definition value.c:6078
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:3352
char * fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together.
Definition value.c:6028
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:3723
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
static size_t char fr_sbuff_t size_t inlen
Definition value.h:997
static size_t char ** out
Definition value.h:997