|
@@ -12,27 +12,29 @@
|
|
|
* This allows you to build complex objects based on their lifetimes, eg:
|
|
* This allows you to build complex objects based on their lifetimes, eg:
|
|
|
*
|
|
*
|
|
|
* struct foo *X = tal(NULL, struct foo);
|
|
* struct foo *X = tal(NULL, struct foo);
|
|
|
- * X->name = tal_strdup(X, "foo");
|
|
|
|
|
|
|
+ * X->val = tal(X, int);
|
|
|
*
|
|
*
|
|
|
- * and the pointer X->name would be a "child" of the tal context "X";
|
|
|
|
|
- * tal_free(X->name) would free X->name as expected, by tal_free(X) would
|
|
|
|
|
- * free X and X->name.
|
|
|
|
|
|
|
+ * and the pointer X->val would be a "child" of the tal context "X";
|
|
|
|
|
+ * tal_free(X->val) would free X->val as expected, by tal_free(X) would
|
|
|
|
|
+ * free X and X->val.
|
|
|
*
|
|
*
|
|
|
* With an overhead of approximately 4 pointers per object
|
|
* With an overhead of approximately 4 pointers per object
|
|
|
* (vs. talloc's 12 pointers), it uses dynamic allocation for
|
|
* (vs. talloc's 12 pointers), it uses dynamic allocation for
|
|
|
* destructors and child lists, so those operations can fail. It does
|
|
* destructors and child lists, so those operations can fail. It does
|
|
|
* not support talloc's references or failing destructors.
|
|
* not support talloc's references or failing destructors.
|
|
|
*
|
|
*
|
|
|
|
|
+ * See Also:
|
|
|
|
|
+ * ccan/tal/str (useful string helpers)
|
|
|
|
|
+ *
|
|
|
* Example:
|
|
* Example:
|
|
|
* #include <stdio.h>
|
|
* #include <stdio.h>
|
|
|
- * #include <stdarg.h>
|
|
|
|
|
* #include <err.h>
|
|
* #include <err.h>
|
|
|
* #include <ccan/talloc/talloc.h>
|
|
* #include <ccan/talloc/talloc.h>
|
|
|
*
|
|
*
|
|
|
* // A structure containing a popened command.
|
|
* // A structure containing a popened command.
|
|
|
* struct command {
|
|
* struct command {
|
|
|
* FILE *f;
|
|
* FILE *f;
|
|
|
- * const char *command;
|
|
|
|
|
|
|
+ * char *command;
|
|
|
* };
|
|
* };
|
|
|
*
|
|
*
|
|
|
* // When struct command is freed, we also want to pclose pipe.
|
|
* // When struct command is freed, we also want to pclose pipe.
|
|
@@ -43,21 +45,22 @@
|
|
|
*
|
|
*
|
|
|
* // This function opens a writable pipe to the given command.
|
|
* // This function opens a writable pipe to the given command.
|
|
|
* static struct command *open_output_cmd(const tal_t *ctx,
|
|
* static struct command *open_output_cmd(const tal_t *ctx,
|
|
|
- * const char *fmt, ...)
|
|
|
|
|
|
|
+ * const char *a0, const char *a1)
|
|
|
* {
|
|
* {
|
|
|
- * va_list ap;
|
|
|
|
|
* struct command *cmd = tal(ctx, struct command);
|
|
* struct command *cmd = tal(ctx, struct command);
|
|
|
*
|
|
*
|
|
|
* if (!cmd)
|
|
* if (!cmd)
|
|
|
* return NULL;
|
|
* return NULL;
|
|
|
*
|
|
*
|
|
|
- * va_start(ap, fmt);
|
|
|
|
|
- * cmd->command = tal_vasprintf(cmd, fmt, ap);
|
|
|
|
|
- * va_end(ap);
|
|
|
|
|
|
|
+ * // Note that tal/str has helpers to make this much easier!
|
|
|
|
|
+ * cmd->command = tal_arrz(cmd, char, strlen(a0) + strlen(a1) + 2);
|
|
|
* if (!cmd->command) {
|
|
* if (!cmd->command) {
|
|
|
* tal_free(cmd);
|
|
* tal_free(cmd);
|
|
|
* return NULL;
|
|
* return NULL;
|
|
|
* }
|
|
* }
|
|
|
|
|
+ * strcat(cmd->command, a0);
|
|
|
|
|
+ * strcat(cmd->command, " ");
|
|
|
|
|
+ * strcat(cmd->command, a1);
|
|
|
*
|
|
*
|
|
|
* cmd->f = popen(cmd->command, "w");
|
|
* cmd->f = popen(cmd->command, "w");
|
|
|
* if (!cmd->f) {
|
|
* if (!cmd->f) {
|
|
@@ -75,7 +78,7 @@
|
|
|
* if (argc != 2)
|
|
* if (argc != 2)
|
|
|
* errx(1, "Usage: %s <command>\n", argv[0]);
|
|
* errx(1, "Usage: %s <command>\n", argv[0]);
|
|
|
*
|
|
*
|
|
|
- * cmd = open_output_cmd(NULL, "%s hello", argv[1]);
|
|
|
|
|
|
|
+ * cmd = open_output_cmd(NULL, argv[1], "hello");
|
|
|
* if (!cmd)
|
|
* if (!cmd)
|
|
|
* err(1, "Running '%s hello'", argv[1]);
|
|
* err(1, "Running '%s hello'", argv[1]);
|
|
|
* fprintf(cmd->f, "This is a test\n");
|
|
* fprintf(cmd->f, "This is a test\n");
|