static char * get_config(char *cmdline) { xenbus_transaction_t txn; char *cfg; int retry; cfg = rumprun_config_path(cmdline); if (cfg != NULL) return cfg; if (xenbus_transaction_start(&txn)) return jsonordie(); if (xenbus_read(txn, "rumprun/cfg", &cfg) != NULL) cfg = jsonordie(); xenbus_transaction_end(txn, 0, &retry); return cfg; }
void rumprun_config(char *cmdline) { char *cfg; struct rumprun_exec *rre; jsmn_parser p; jsmntok_t *tokens = NULL; jsmntok_t *t; size_t cmdline_len; unsigned int i; int ntok; /* is the config file on rootfs? if so, mount & dig it out */ cfg = rumprun_config_path(cmdline); if (cfg != NULL) { cmdline = getcmdlinefromroot(cfg); if (cmdline == NULL) errx(1, "could not get cfg from rootfs"); } while (*cmdline != '{') { if (*cmdline == '\0') { warnx("could not find start of json. no config?"); makeargv(strdup("rumprun")); return; } cmdline++; } cmdline_len = strlen(cmdline); jsmn_init(&p); ntok = jsmn_parse(&p, cmdline, cmdline_len, NULL, 0); if (ntok <= 0) { errx(1, "json parse failed 1"); } tokens = malloc(ntok * sizeof(*t)); if (!tokens) { errx(1, "failed to allocate jsmn tokens"); } jsmn_init(&p); if ((ntok = jsmn_parse(&p, cmdline, cmdline_len, tokens, ntok)) < 1) { errx(1, "json parse failed 2"); } T_CHECKTYPE(tokens, cmdline, JSMN_OBJECT, __func__); for (t = &tokens[0]; t < &tokens[ntok]; ) { /* allow multiple levels of object nesting */ if (t->type == JSMN_OBJECT) { t++; continue; } T_CHECKTYPE(t, cmdline, JSMN_STRING, __func__); for (i = 0; i < __arraycount(parsers); i++) { if (T_STREQ(t, cmdline, parsers[i].name)) { int left; t++; left = &tokens[ntok] - t; t += parsers[i].handler(t, left, cmdline); break; } } if (i == __arraycount(parsers)) errx(1, "no match for key \"%.*s\"", T_PRINTFSTAR(t, cmdline)); } /* * Before we start running things, perform some sanity checks */ rre = TAILQ_LAST(&rumprun_execs, rumprun_execs); if (rre == NULL) { errx(1, "rumprun_config: no bins"); } if (rre->rre_flags & RUMPRUN_EXEC_PIPE) { errx(1, "rumprun_config: last bin may not output to pipe"); } free(tokens); }