Add a json_do_string() a function to print a JSON string. This function does the needed encoding of control chars and escape chars. I skipped the optional encoding of the forward slash (/) since this is only needed if the json output is embedded in HTML/SGML/XML. People putting JSON into such documents need to pass this through an extra step.
This implements json_do_printf() now as a wrapper around json_do_string(). All users of json_do_printf(name, "%s", value) can be converted to json_do_string(). I will do this is a subsequent step. -- :wq Claudio Index: json.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/json.c,v retrieving revision 1.1 diff -u -p -r1.1 json.c --- json.c 27 Apr 2023 07:57:25 -0000 1.1 +++ json.c 1 May 2023 20:07:26 -0000 @@ -19,6 +19,7 @@ #include <err.h> #include <stdarg.h> #include <stdint.h> +#include <stdlib.h> #include <stdio.h> #include <string.h> @@ -179,16 +180,64 @@ void json_do_printf(const char *name, const char *fmt, ...) { va_list ap; + char *str; - do_comma_indent(); + va_start(ap, fmt); + if (!eb) { + if (vasprintf(&str, fmt, ap) == -1) + errx(1, "json printf failed"); + json_do_string(name, str); + free(str); + } + va_end(ap); +} +void +json_do_string(const char *name, const char *v) +{ + int c; + + do_comma_indent(); do_name(name); if (!eb) eb = fprintf(jsonfh, "\"") < 0; - va_start(ap, fmt); - if (!eb) - eb = vfprintf(jsonfh, fmt, ap) < 0; - va_end(ap); + while ((c = *v++) != '\0') { + /* skip escaping '/' since our use case does not require it */ + switch(c) { + case '"': + if (!eb) + eb = fprintf(jsonfh, "\\\"") < 0; + break; + case '\\': + if (!eb) + eb = fprintf(jsonfh, "\\\\") < 0; + break; + case '\b': + if (!eb) + eb = fprintf(jsonfh, "\\b") < 0; + break; + case '\f': + if (!eb) + eb = fprintf(jsonfh, "\\f") < 0; + break; + case '\n': + if (!eb) + eb = fprintf(jsonfh, "\\n") < 0; + break; + case '\r': + if (!eb) + eb = fprintf(jsonfh, "\\r") < 0; + break; + case '\t': + if (!eb) + eb = fprintf(jsonfh, "\\t") < 0; + break; + default: + if (!eb) + eb = putc(c, jsonfh) == EOF; + break; + } + } if (!eb) eb = fprintf(jsonfh, "\"") < 0; } Index: json.h =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/json.h,v retrieving revision 1.1 diff -u -p -r1.1 json.h --- json.h 27 Apr 2023 07:57:25 -0000 1.1 +++ json.h 30 Apr 2023 15:11:36 -0000 @@ -26,6 +26,7 @@ void json_do_object(const char *); void json_do_end(void); void json_do_printf(const char *, const char *, ...) __attribute__((__format__ (printf, 2, 3))); +void json_do_string(const char *, const char *); void json_do_hexdump(const char *, void *, size_t); void json_do_bool(const char *, int); void json_do_uint(const char *, unsigned long long);