mirror of
https://github.com/troglobit/finit.git
synced 2026-10-01 05:22:48 +07:00
initctl: escape special characters in JSON output
Strings like command, description, and environment may contain characters that need escaping for valid JSON, e.g., embedded quotes in command line arguments like -V "NanoPi R2S". Add json_escape() helper to handle quotes, backslashes, and control chars. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+69
-9
@@ -1036,6 +1036,62 @@ static int svc_compare(svc_t *svc, char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Escape a string for safe JSON output. Handles quotes, backslashes,
|
||||
* and control characters. Returns pointer to static buffer.
|
||||
*/
|
||||
static char *json_escape(const char *str)
|
||||
{
|
||||
static char buf[1024];
|
||||
char *ptr = buf;
|
||||
size_t left = sizeof(buf) - 1;
|
||||
|
||||
if (!str)
|
||||
return "";
|
||||
|
||||
while (*str && left > 1) {
|
||||
char c = *str++;
|
||||
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = c;
|
||||
left -= 2;
|
||||
break;
|
||||
case '\n':
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 'n';
|
||||
left -= 2;
|
||||
break;
|
||||
case '\r':
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 'r';
|
||||
left -= 2;
|
||||
break;
|
||||
case '\t':
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = 't';
|
||||
left -= 2;
|
||||
break;
|
||||
default:
|
||||
if ((unsigned char)c < 0x20) {
|
||||
/* Other control chars: use \uXXXX */
|
||||
int n = snprintf(ptr, left, "\\u%04x", (unsigned char)c);
|
||||
ptr += n;
|
||||
left -= n;
|
||||
} else {
|
||||
*ptr++ = c;
|
||||
left--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
|
||||
{
|
||||
long now = jiffies();
|
||||
@@ -1051,14 +1107,16 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
|
||||
fprintf(fp,
|
||||
"%s"
|
||||
"%s{\n"
|
||||
"%s \"identity\": \"%s\",\n"
|
||||
"%s \"description\": \"%s\",\n"
|
||||
"%s \"identity\": \"%s\",\n",
|
||||
prev ? ",\n" : indent, prev ? indent : "",
|
||||
indent, svc_ident(svc, NULL, 0));
|
||||
fprintf(fp,
|
||||
"%s \"description\": \"%s\",\n",
|
||||
indent, json_escape(svc->desc));
|
||||
fprintf(fp,
|
||||
"%s \"type\": \"%s\",\n"
|
||||
"%s \"forking\": %s,\n"
|
||||
"%s \"status\": \"%s\",\n",
|
||||
prev ? ",\n" : indent, prev ? indent : "",
|
||||
indent, svc_ident(svc, NULL, 0),
|
||||
indent, svc->desc,
|
||||
indent, svc_typestr(svc),
|
||||
indent, svc->forking ? "true" : "false",
|
||||
indent, svc_status(svc));
|
||||
@@ -1080,15 +1138,17 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
|
||||
}
|
||||
|
||||
fprintf(fp,
|
||||
"%s \"origin\": \"%s\",\n"
|
||||
"%s \"origin\": \"%s\",\n",
|
||||
indent, svc->file[0] ? svc->file : "built-in");
|
||||
svc_command(svc, buf, sizeof(buf), 0);
|
||||
fprintf(fp,
|
||||
"%s \"command\": \"%s\",\n",
|
||||
indent, svc->file[0] ? svc->file : "built-in",
|
||||
indent, svc_command(svc, buf, sizeof(buf), 0));
|
||||
indent, json_escape(buf));
|
||||
|
||||
svc_environ(svc, buf, sizeof(buf), 0);
|
||||
if (buf[0])
|
||||
fprintf(fp,
|
||||
"%s \"environment\": \"%s\",\n", indent, buf);
|
||||
"%s \"environment\": \"%s\",\n", indent, json_escape(buf));
|
||||
|
||||
svc_cond(svc, buf, sizeof(buf), 0);
|
||||
if (buf[0])
|
||||
|
||||
Reference in New Issue
Block a user