summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2010-02-20 19:55:05 -0800
committerRuss Allbery <rra@stanford.edu>2010-02-20 19:55:05 -0800
commita3ee976840e97d37022ec117bae09fef25ac4385 (patch)
treea2422d730079e2ce72f0245f5497685f27377960 /client
parent77581a6a1620118ca17e26ec8b549603ab67b91b (diff)
Add support in the wallet client for store of binary data
Refactor the wallet client code to use remctl_commandv and send stores with data containing nul.
Diffstat (limited to 'client')
-rw-r--r--client/file.c20
-rw-r--r--client/internal.h25
-rw-r--r--client/remctl.c53
-rw-r--r--client/wallet.c34
4 files changed, 84 insertions, 48 deletions
diff --git a/client/file.c b/client/file.c
index c9edf3a..66d5f63 100644
--- a/client/file.c
+++ b/client/file.c
@@ -115,14 +115,13 @@ get_file(struct remctl *r, const char *prefix, const char *type,
/*
- * Read all of a file into memory and return the contents as a newly allocated
- * string. Handles a file name of "-" to mean standard input. Dies on any
- * failure.
- *
- * This will need modification later when we want to handle nul characters.
+ * Read all of a file into memory and return the contents in newly allocated
+ * memory. Returns the size of the file contents in the second argument if
+ * it's not NULL. Handles a file name of "-" to mean standard input. Dies on
+ * any failure.
*/
-char *
-read_file(const char *name)
+void *
+read_file(const char *name, size_t *length)
{
char *contents;
size_t size, offset;
@@ -140,7 +139,7 @@ read_file(const char *name)
sysdie("cannot open file %s", name);
if (fstat(fd, &st) < 0)
sysdie("cannot stat file %s", name);
- size = st.st_size + 1;
+ size = st.st_size;
contents = xmalloc(size);
}
offset = 0;
@@ -157,8 +156,7 @@ read_file(const char *name)
offset += status;
} while (status > 0);
close(fd);
- contents[offset] = '\0';
- if (memchr(contents, '\0', offset) != NULL)
- die("cannot yet handle file data containing nul characters");
+ if (length != NULL)
+ *length = offset;
return contents;
}
diff --git a/client/internal.h b/client/internal.h
index 7fe962b..d82196c 100644
--- a/client/internal.h
+++ b/client/internal.h
@@ -17,6 +17,7 @@
/* Forward declarations to avoid unnecessary includes. */
struct remctl;
+struct iovec;
BEGIN_DECLS
@@ -29,14 +30,18 @@ void kinit(krb5_context, const char *principal);
void kdestroy(void);
/*
- * Given a remctl object, run a remctl command. If data is non-NULL, saves
- * the standard output from the command into data with the length in length.
- * Otherwise, prints it to standard output. Either way, prints standard error
- * output and errors to standard error and returns the exit status or 255 for
- * a remctl internal error.
+ * Given a remctl object, either a NULL-terminated array of strings or an
+ * array of iovecs and the number of elements in the array, and optional data
+ * and size output variables, run a remctl command. If data is non-NULL,
+ * saves the standard output from the command into data with the length in
+ * length. Otherwise, prints it to standard output. Either way, prints
+ * standard error output and errors to standard error and returns the exit
+ * status or 255 for a remctl internal error.
*/
int run_command(struct remctl *, const char **command, char **data,
size_t *length);
+int run_commandv(struct remctl *, const struct iovec *command, size_t count,
+ char **data, size_t *length);
/*
* Check whether an object exists using the exists wallet interface. Returns
@@ -91,12 +96,12 @@ void write_srvtab(krb5_context, const char *srvtab, const char *principal,
const char *keytab);
/*
- * Read all of a file into memory and return the contents as a newly allocated
- * string. Handles a file name of "-" to mean standard input. Dies on any
- * failure. This will need modification later when we want to handle nul
- * characters.
+ * Read all of a file into memory and return the contents in newly allocated
+ * memory. Handles a file name of "-" to mean standard input. Stores the
+ * length of the data in the second argument if it isn't NULL. Dies on any
+ * failure.
*/
-char *read_file(const char *);
+void *read_file(const char *, size_t *);
END_DECLS
diff --git a/client/remctl.c b/client/remctl.c
index a4ff097..5a541d5 100644
--- a/client/remctl.c
+++ b/client/remctl.c
@@ -18,15 +18,14 @@
/*
- * Given a remctl connection and a command, run the command.
- *
- * If data is non-NULL, save the output in it and return the length in length.
- * Otherwise, send any output to stdout. Either way, send error output to
- * stderr, and return the exit status (or 255 if there is an error).
+ * Retrieve the results of a remctl command, which should be issued prior to
+ * calling this function. If data is non-NULL, save the output in it and
+ * return the length in length. Otherwise, send any output to stdout. Either
+ * way, send error output to stderr, and return the exit status (or 255 if
+ * there is an error).
*/
-int
-run_command(struct remctl *r, const char **command, char **data,
- size_t *length)
+static int
+command_results(struct remctl *r, char **data, size_t *length)
{
struct remctl_output *output;
int status = 255;
@@ -35,10 +34,6 @@ run_command(struct remctl *r, const char **command, char **data,
*data = NULL;
if (length != NULL)
*length = 0;
- if (!remctl_command(r, command)) {
- warn("%s", remctl_error(r));
- return 255;
- }
do {
output = remctl_output(r);
switch (output->type) {
@@ -74,6 +69,40 @@ run_command(struct remctl *r, const char **command, char **data,
/*
+ * Given a remctl connection and a NULL-terminated array of strings, run the
+ * command and return the results using command_results, optionally putting
+ * output into the data variable.
+ */
+int
+run_command(struct remctl *r, const char **command, char **data,
+ size_t *length)
+{
+ if (!remctl_command(r, command)) {
+ warn("%s", remctl_error(r));
+ return 255;
+ }
+ return command_results(r, data, length);
+}
+
+
+/*
+ * Given a remctl connection, an array of iovecs, and the length of the array,
+ * run the command and return the results using command_results, optionally
+ * putting output into the data variable.
+ */
+int
+run_commandv(struct remctl *r, const struct iovec *command, size_t count,
+ char **data, size_t *length)
+{
+ if (!remctl_commandv(r, command, count)) {
+ warn("%s", remctl_error(r));
+ return 255;
+ }
+ return command_results(r, data, length);
+}
+
+
+/*
* Check whether an object exists using the exists wallet interface. Returns
* true if it does, false if it doesn't, and dies on remctl errors.
*/
diff --git a/client/wallet.c b/client/wallet.c
index ce0f4e7..dc4fe18 100644
--- a/client/wallet.c
+++ b/client/wallet.c
@@ -135,7 +135,8 @@ main(int argc, char *argv[])
krb5_error_code retval;
struct options options;
int option, i, status;
- const char **command;
+ struct iovec *command;
+ size_t count, length;
const char *file = NULL;
const char *srvtab = NULL;
struct remctl *r;
@@ -241,24 +242,27 @@ main(int argc, char *argv[])
status = get_file(r, options.type, argv[1], argv[2], file);
}
} else {
+ count = argc + 1;
if (strcmp(argv[0], "store") == 0) {
if (argc > 4)
die("too many arguments");
- else if (argc == 4)
- command = xmalloc(sizeof(char *) * (argc + 2));
- else
- command = xmalloc(sizeof(char *) * (argc + 3));
- } else
- command = xmalloc(sizeof(char *) * (argc + 2));
- command[0] = options.type;
- for (i = 0; i < argc; i++)
- command[i + 1] = argv[i];
+ else if (argc < 4)
+ count++;
+ }
+ command = xmalloc(sizeof(struct iovec) * count);
+ command[0].iov_base = (char *) options.type;
+ command[0].iov_len = strlen(options.type);
+ for (i = 0; i < argc; i++) {
+ command[i + 1].iov_base = argv[i];
+ command[i + 1].iov_len = strlen(argv[i]);
+ }
if (strcmp(argv[0], "store") == 0 && argc < 4) {
- command[argc + 1] = read_file(file == NULL ? "-" : file);
- command[argc + 2] = NULL;
- } else
- command[argc + 1] = NULL;
- status = run_command(r, command, NULL, NULL);
+ if (file == NULL)
+ file = "-";
+ command[argc + 1].iov_base = read_file(file, &length);
+ command[argc + 1].iov_len = length;
+ }
+ status = run_commandv(r, command, count, NULL, NULL);
}
remctl_close(r);
krb5_free_context(ctx);