static char *get_leaks(char *lines[], char **errs) { char *leaks = tal_strdup(lines, ""); unsigned int i; for (i = 0; i < tal_count(lines) - 1; i++) { if (strstr(lines[i], " lost ")) { /* A leak... */ if (strstr(lines[i], " definitely lost ")) { /* Definite leak, report. */ while (lines[i] && !blank_line(lines[i])) { tal_append_fmt(&leaks, "%s\n", lines[i]); i++; } } else /* Not definite, ignore. */ while (lines[i] && !blank_line(lines[i])) i++; } else { /* A real error. */ while (lines[i] && !blank_line(lines[i])) { if (!*errs) *errs = tal_fmt(NULL, "%s\n", lines[i]); else tal_append_fmt(errs, "%s\n", lines[i]); i++; } } } return leaks; }
static void json_start_member(char **result, const char *fieldname) { /* Prepend comma if required. */ if (**result && !strends(*result, "{ ") && !strends(*result, "[ ")) tal_append_fmt(result, ", "); if (fieldname) tal_append_fmt(result, "\"%s\" : ", fieldname); }
void json_object_start(char **ptr, const char *fieldname) { unsigned int indents = strcount(*ptr, "{") + strcount(*ptr, "[") - (strcount(*ptr, "]") + strcount(*ptr, "}")); json_start_member(ptr, fieldname); if (indents) { tal_append_fmt(ptr, "\n"); while (indents--) tal_append_fmt(ptr, "\t"); } tal_append_fmt(ptr, "{ "); }
static void start_main(char **ret, const char *why) { tal_append_fmt(ret, "/* The example %s, so fake function wrapper inserted */\n" "int main(int argc, char *argv[])\n" "{\n", why); }
static char *cflags_list(const struct manifest *m) { unsigned int i; char *ret = tal_strdup(m, cflags); char **flags = get_cflags(m, m->dir, get_or_compile_info); for (i = 0; flags[i]; i++) tal_append_fmt(&ret, " %s", flags[i]); return ret; }
static char *example_obj_list(const void *ctx, struct manifest **deps) { char *list = tal_strdup(ctx, ""); unsigned int i; for (i = 0; i < tal_count(deps); i++) { if (deps[i]->compiled[COMPILE_NORMAL]) tal_append_fmt(&list, " %s", deps[i]->compiled[COMPILE_NORMAL]); } return list; }
static struct command_result *waitsendpay_expired(struct command *cmd, struct pay_command *pc) { char *errmsg, *data; errmsg = tal_fmt(pc, "Gave up after %zu attempts", tal_count(pc->ps->attempts)); data = tal_strdup(pc, "'attempts': [ "); for (size_t i = 0; i < tal_count(pc->ps->attempts); i++) { if (pc->ps->attempts[i].route) tal_append_fmt(&data, "%s { 'route': %s,\n 'failure': %s\n }", i == 0 ? "" : ",", pc->ps->attempts[i].route, pc->ps->attempts[i].failure); else tal_append_fmt(&data, "%s { 'failure': %s\n }", i == 0 ? "" : ",", pc->ps->attempts[i].failure); } tal_append_fmt(&data, "]"); return command_done_err(cmd, PAY_STOPPED_RETRYING, errmsg, data); }
static char *example_lib_list(const void *ctx, struct manifest **deps) { char *list = tal_strdup(ctx, ""); char **libs; unsigned int i, j; /* FIXME: This doesn't uniquify. */ for (i = 0; i < tal_count(deps); i++) { libs = get_libs(ctx, deps[i]->dir, NULL, get_or_compile_info); for (j = 0; libs[j]; j++) tal_append_fmt(&list, "-l%s ", libs[j]); } return list; }
static void complain(struct parse_state *ps, const char *complaint) { unsigned int linenum; const char *p = ps->code; for (linenum = 1; p < ps->toks[0].p; linenum++) { p = strchr(p+1, '\n'); if (!p) break; } tal_append_fmt(&ps->complaints, "Line %u: '%.*s': %s\n", linenum, (int)ps->toks[0].len, ps->toks[0].p, complaint); }
static const char *join_routehint(const tal_t *ctx, const char *buf, const jsmntok_t *route, const struct pay_command *pc, const struct route_info *routehint) { char *ret; /* Truncate closing ] from route */ ret = tal_strndup(ctx, buf + route->start, route->end - route->start - 1); for (size_t i = 0; i < tal_count(routehint); i++) { /* amount to be received by *destination* */ struct amount_msat dest_amount; if (!route_msatoshi(&dest_amount, pc->msat, routehint + i + 1, tal_count(routehint) - i - 1)) return tal_free(ret); tal_append_fmt(&ret, ", {" " 'id': '%s'," " 'channel': '%s'," " 'msatoshi': '%s'," " 'delay': %u }", /* pubkey of *destination* */ route_pubkey(tmpctx, pc, routehint, i + 1), type_to_string(tmpctx, struct short_channel_id, &routehint[i].short_channel_id), type_to_string(tmpctx, struct amount_msat, &dest_amount), /* cltv for *destination* */ route_cltv(pc->final_cltv, routehint + i + 1, tal_count(routehint) - i - 1)); } /* Put ] back */ tal_append_fmt(&ret, "]"); return ret; }
void json_add_bool(char **result, const char *fieldname, bool value) { json_start_member(result, fieldname); tal_append_fmt(result, value ? "true" : "false"); }
void json_array_end(char **ptr) { tal_append_fmt(ptr, " ]"); }
void json_object_end(char **ptr) { tal_append_fmt(ptr, " }"); }
void json_add_num(char **result, const char *fieldname, unsigned int value) { json_start_member(result, fieldname); tal_append_fmt(result, "%u", value); }
void json_add_literal(char **result, const char *fieldname, const char *literal, int len) { json_start_member(result, fieldname); tal_append_fmt(result, "%.*s", len, literal); }
void json_add_string(char **result, const char *fieldname, const char *value) { json_start_member(result, fieldname); tal_append_fmt(result, "\"%s\"", value); }
/* Simple test code to create a gateway transaction */ int main(int argc, char *argv[]) { int fd, i, off; const char *method; char *cmd, *resp, *idstr, *rpc_filename; char *result_end; struct sockaddr_un addr; jsmntok_t *toks; const jsmntok_t *result, *error, *id; char *pettycoin_dir; const tal_t *ctx = tal(NULL, char); size_t num_opens, num_closes; bool valid; err_set_progname(argv[0]); opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn); pettycoin_dir_register_opts(ctx, &pettycoin_dir, &rpc_filename); opt_register_noarg("--help|-h", opt_usage_and_exit, "<command> [<params>...]", "Show this message"); opt_register_noarg("--version|-V", opt_version_and_exit, VERSION, "Display version and exit"); opt_early_parse(argc, argv, opt_log_stderr_exit); opt_parse(&argc, argv, opt_log_stderr_exit); method = argv[1]; if (!method) errx(ERROR_USAGE, "Need at least one argument\n%s", opt_usage(argv[0], NULL)); if (chdir(pettycoin_dir) != 0) err(ERROR_TALKING_TO_PETTYCOIN, "Moving into '%s'", pettycoin_dir); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (strlen(rpc_filename) + 1 > sizeof(addr.sun_path)) errx(ERROR_USAGE, "rpc filename '%s' too long", rpc_filename); strcpy(addr.sun_path, rpc_filename); addr.sun_family = AF_UNIX; if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) err(ERROR_TALKING_TO_PETTYCOIN, "Connecting to '%s'", rpc_filename); idstr = tal_fmt(ctx, "pettycoin_query-%i", getpid()); cmd = tal_fmt(ctx, "{ \"method\" : \"%s\", \"id\" : \"%s\", \"params\" : [ ", method, idstr); for (i = 2; i < argc; i++) { /* Numbers are left unquoted, and quoted things left alone. */ if (strspn(argv[i], "0123456789") == strlen(argv[i]) || argv[i][0] == '"') tal_append_fmt(&cmd, "%s", argv[i]); else tal_append_fmt(&cmd, "\"%s\"", argv[i]); if (i != argc - 1) tal_append_fmt(&cmd, ", "); } tal_append_fmt(&cmd, "] }"); if (!write_all(fd, cmd, strlen(cmd))) err(ERROR_TALKING_TO_PETTYCOIN, "Writing command"); resp = tal_arr(cmd, char, 100); off = 0; num_opens = num_closes = 0; while ((i = read(fd, resp + off, tal_count(resp) - 1 - off)) > 0) { resp[off + i] = '\0'; num_opens += strcount(resp + off, "{"); num_closes += strcount(resp + off, "}"); off += i; if (off == tal_count(resp) - 1) tal_resize(&resp, tal_count(resp) * 2); /* parsing huge outputs is slow: do quick check first. */ if (num_opens == num_closes && strstr(resp, "\"result\"")) break; } if (i < 0) err(ERROR_TALKING_TO_PETTYCOIN, "reading response"); /* Parsing huge results is too slow, so hack fastpath common case */ result_end = tal_fmt(ctx, ", \"error\" : null, \"id\" : \"%s\" }\n", idstr); if (strstarts(resp, "{ \"result\" : ") && strends(resp, result_end)) { /* Result is OK, so dump it */ resp += strlen("{ \"result\" : "); printf("%.*s\n", (int)(strlen(resp) - strlen(result_end)), resp); tal_free(ctx); return 0; } toks = json_parse_input(resp, off, &valid); if (!toks || !valid) errx(ERROR_TALKING_TO_PETTYCOIN, "Malformed response '%s'", resp); result = json_get_member(resp, toks, "result"); if (!result) errx(ERROR_TALKING_TO_PETTYCOIN, "Missing 'result' in response '%s'", resp); error = json_get_member(resp, toks, "error"); if (!error) errx(ERROR_TALKING_TO_PETTYCOIN, "Missing 'error' in response '%s'", resp); id = json_get_member(resp, toks, "id"); if (!id) errx(ERROR_TALKING_TO_PETTYCOIN, "Missing 'id' in response '%s'", resp); if (!json_tok_streq(resp, id, idstr)) errx(ERROR_TALKING_TO_PETTYCOIN, "Incorrect 'id' in response: %.*s", json_tok_len(id), json_tok_contents(resp, id)); if (json_tok_is_null(resp, error)) { printf("%.*s\n", json_tok_len(result), json_tok_contents(resp, result)); tal_free(ctx); return 0; } printf("%.*s\n", json_tok_len(error), json_tok_contents(resp, error)); tal_free(ctx); return 1; }
void json_add_null(char **result, const char *fieldname) { json_start_member(result, fieldname); tal_append_fmt(result, "null"); }
int main(void) { char *parent, *c; plan_tests(43); parent = tal(NULL, char); ok1(parent); c = tal_strdup(parent, "hello"); ok1(strcmp(c, "hello") == 0); ok1(tal_parent(c) == parent); ok1(tal_count(c) == strlen(c) + 1); tal_free(c); c = tal_strndup(parent, "hello", 3); ok1(strcmp(c, "hel") == 0); ok1(tal_parent(c) == parent); ok1(tal_count(c) == strlen(c) + 1); tal_free(c); #ifdef TAL_USE_TALLOC c = tal_talloc_typechk_(parent, char *); #else c = tal_typechk_(parent, char *); #endif c = tal_dup_arr(parent, char, "hello", 6, 0); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_count(c) == 6); ok1(tal_parent(c) == parent); tal_free(c); /* Now with an extra byte. */ c = tal_dup_arr(parent, char, "hello", 6, 1); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_count(c) == 7); ok1(tal_parent(c) == parent); strcat(c, "x"); tal_free(c); c = tal_fmt(parent, "hello %s", "there"); ok1(strcmp(c, "hello there") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); tal_free(c); c = tal_strcat(parent, "hello ", "there"); ok1(strcmp(c, "hello there") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); /* Make sure take works correctly. */ c = tal_strcat(parent, take(c), " again"); ok1(strcmp(c, "hello there again") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); c = tal_strcat(parent, "And ", take(c)); ok1(tal_count(c) == strlen(c) + 1); ok1(strcmp(c, "And hello there again") == 0); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); /* NULL pass through works... */ c = tal_strcat(parent, take(NULL), take(c)); ok1(!c); ok1(no_children(parent)); c = tal_strcat(parent, take(tal_strdup(parent, "hi")), take(NULL)); ok1(!c); ok1(no_children(parent)); c = tal_strcat(parent, take(NULL), take(NULL)); ok1(!c); ok1(no_children(parent)); /* Appending formatted strings. */ c = tal_strdup(parent, "hi"); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_append_fmt(&c, "%s %s", "there", "world")); ok1(strcmp(c, "hithere world") == 0); ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(!tal_append_fmt(&c, take(NULL), "there", "world")); ok1(strcmp(c, "hithere world") == 0); ok1(tal_count(c) == strlen(c) + 1); tal_free(parent); return exit_status(); }