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