static char * token2cstr(jsmntok_t *t, char *data) { *(T_STR(t, data) + T_SIZE(t)) = '\0'; return T_STR(t, data); }
/* * "rc": [ * { "bin" : "binname", * "argv" : [ "arg1", "arg2", ... ], (optional) * "runmode" : "& OR |" (optional) * }, * .... * ] */ static int addbin(jsmntok_t *t, char *data) { jsmntok_t *t_bin, *t_argv, *t_runmode; struct rumprun_exec *rre; jsmntok_t *key, *value; char *binname; int binsize = 1; int objleft = t->size; int rreflags, i; T_CHECKTYPE(t, data, JSMN_OBJECT, __func__); t++; /* process and validate data */ t_bin = t_argv = t_runmode = NULL; while (objleft--) { int mysize; key = t; value = t+1; T_CHECKTYPE(key, data, JSMN_STRING, __func__); if (T_STREQ(key, data, "bin")) { t_bin = value; T_CHECKSIZE(key, data, 1, __func__); T_CHECKTYPE(value, data, JSMN_STRING, __func__); T_CHECKSIZE(value, data, 0, __func__); mysize = 1 + 1; } else if (T_STREQ(key, data, "argv")) { T_CHECKTYPE(value, data, JSMN_ARRAY, __func__); t_argv = value; /* key + array + array contents */ mysize = 1 + 1 + value->size; } else if (T_STREQ(key, data, "runmode")) { t_runmode = value; T_CHECKSIZE(key, data, 1, __func__); T_CHECKTYPE(value, data, JSMN_STRING, __func__); T_CHECKSIZE(value, data, 0, __func__); mysize = 1 + 1; } else { errx(1, "unexpected key \"%.*s\" in \"%s\"", T_PRINTFSTAR(key, data), __func__); } t += mysize; binsize += mysize; } if (!t_bin) errx(1, "missing \"bin\" for rc entry"); binname = token2cstr(t_bin, data); if (t_runmode) { bool sizeok = T_SIZE(t_runmode) == 1; if (sizeok && *T_STR(t_runmode,data) == '&') { rreflags = RUMPRUN_EXEC_BACKGROUND; } else if (sizeok && *T_STR(t_runmode,data) == '|') { rreflags = RUMPRUN_EXEC_PIPE; } else { errx(1, "invalid runmode \"%.*s\" for bin \"%.*s\"", T_PRINTFSTAR(t_runmode, data), T_PRINTFSTAR(t_bin, data)); } } else { rreflags = 0; } /* ok, we got everything. save into rumprun_exec structure */ rre = malloc(sizeof(*rre) + (2+t_argv->size) * sizeof(char *)); if (rre == NULL) err(1, "allocate rumprun_exec"); rre->rre_flags = rreflags; rre->rre_argc = 1+t_argv->size; rre->rre_argv[0] = binname; for (i = 1, t = t_argv+1; i <= t_argv->size; i++, t++) { T_CHECKTYPE(t, data, JSMN_STRING, __func__); rre->rre_argv[i] = token2cstr(t, data); } rre->rre_argv[rre->rre_argc] = NULL; TAILQ_INSERT_TAIL(&rumprun_execs, rre, rre_entries); return binsize; }
int test_str(void) { STR_DEFINE( s3, 10 ); Str *s4, *s5; STR_DEFINE(s6, 10); STR_DEFINE(s7, 10); dump_str( s1, "s1" ); dump_str( s2, "s2" ); dump_str( s3, "s3" ); /* check static strings keep their value */ mu_assert_str( static_str(4), ==, "4" ); mu_assert_str( static_str(-1), ==, "4" ); mu_assert_str( static_str(-1), ==, "4" ); mu_assert_str( static_str(7), ==, "7" ); mu_assert_str( static_str(-1), ==, "7" ); mu_assert_str( static_str(-1), ==, "7" ); T_STR(s4, s4 = str_new(6)); /* alloc, keep memory leak */ T_STR(s5, s5 = str_new(6)); /* expand */ T_STR(s3, str_clear(s3)); T_STR(s3, str_reserve(s3, 9)); T_STR(s3, str_reserve(s3, 10)); T_STR(s3, str_reserve(s3, 11)); T_STR(s3, str_clear(s3)); /* char */ T_STR(s4, str_set(s4, "xxxx")); T_STR(s4, str_set_char(s4, 0)); T_STR(s4, str_append_char(s4, 1)); T_STR(s4, str_append_char(s4, 2)); T_STR(s4, str_append_char(s4, 3)); T_STR(s4, str_append_char(s4, 4)); T_STR(s4, str_append_char(s4, 5)); T_STR(s4, str_append_char(s4, 6)); T_STR(s4, str_append_char(s4, 7)); T_STR(s4, str_append_char(s4, 8)); T_STR(s4, str_append_char(s4, 9)); T_STR(s4, str_append_char(s4, 10)); T_STR(s4, str_clear(s4)); /* string */ T_STR(s5, str_set(s5, "1234")); T_STR(s5, str_append(s5, "56789")); T_STR(s5, str_append(s5, "0")); T_STR(s5, str_clear(s5)); /* substring */ T_STR(s5, str_set_n(s5, "1234xx", 4)); T_STR(s5, str_append_n(s5, "56789xx", 5)); T_STR(s5, str_append_n(s5, "01234567890xx", 11)); T_STR(s5, str_clear(s5)); /* bytes */ T_STR(s5, str_set_bytes(s5, "\0\1\2\3x", 3)); T_STR(s5, str_append_bytes(s5, "\4\5\6x", 3)); T_STR(s5, str_clear(s5)); /* sprintf - test repeated call to vsprintf when buffer grows, needs va_copy in MacOS */ T_STR(s6, str_set(s6, "xxxx")); T_STR(s6, str_sprintf(s6, "%s %d", "hello", 123)); T_STR(s6, str_sprintf(s6, "%s %d", "hello", 1234)); T_STR(s6, str_append_sprintf(s6, "%s %d", "hello", 12345)); T_STR(s6, str_clear(s6)); /* vsprintf - test repeated call to vsprintf when buffer grows, needs va_copy in MacOS */ T_STR(s7, str_set(s7, "xxxx")); T_STR(s7, call_vsprintf(s7, "%s %d", "hello", 123)); T_STR(s7, call_vsprintf(s7, "%s %d", "hello", 1234)); T_STR(s7, call_append_vsprintf(s7, "%s %d", "hello", 12345)); T_STR(s7, str_clear(s7)); str_delete(s5); mu_assert_ptr_null(s5); STR_DELETE(s3); mu_assert_ptr_null(s3); STR_DELETE(s6); mu_assert_ptr_null(s6); STR_DELETE(s7); mu_assert_ptr_null(s7); return MU_PASS; }