Add -e option for encoding arguments as strings

main
cel 6 years ago
parent 1938337af3
commit 1412c8b5f9

@ -16,7 +16,7 @@ sudo make install
## Usage ## Usage
```sh ```sh
sbotc [-j] [-T] [-l] [-r] sbotc [-j] [-T] [-l] [-r] [-e]
[ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ] [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]
[ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ] [ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]
[ -a | [-t <type>] <method> [<argument>...] ] [ -a | [-t <type>] <method> [<argument>...] ]

@ -11,6 +11,7 @@
.Op Fl l .Op Fl l
.Op Fl r .Op Fl r
.Op Fl T .Op Fl T
.Op Fl e
.Op Fl a .Op Fl a
. .
.Oo .Oo
@ -52,6 +53,8 @@ Don't output newlines after string or JSON packets.
.It Fl r .It Fl r
Raw mode. Disables stdin line buffering/editing and echoing. Implies Raw mode. Disables stdin line buffering/editing and echoing. Implies
.Fl l . .Fl l .
.It Fl e
Encode arguments as strings, rather than expecting them to be JSON-encoded.
.It Fl T .It Fl T
Test using shs1-testsuite protocol. Instead of connecting to a server and running Test using shs1-testsuite protocol. Instead of connecting to a server and running
a command, connect to stdio. On successful handshake, output concatenation of a command, connect to stdio. On successful handshake, output concatenation of
@ -104,7 +107,9 @@ Default is to look up the method in
.It Ar method .It Ar method
Method name. Method name.
.It Op Ar argument ... .It Op Ar argument ...
Arguments to pass to the method call. Each argument must be JSON-encoded. Arguments to pass to the method call. Each argument must be JSON-encoded, unless the
.Fl e
option is used, in which the arguments are treated as strings.
.El .El
.Sh ENVIRONMENT .Sh ENVIRONMENT
.Bl -tag .Bl -tag

@ -112,7 +112,7 @@ static void reset_termios() {
} }
static void usage() { static void usage() {
fputs("usage: sbotc [-j] [-T] [-l] [-r]\n" fputs("usage: sbotc [-j] [-T] [-l] [-r] [-e]\n"
" [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n" " [ -n | [-c <cap>] [-k <key>] [-K <keypair_seed>] ]\n"
" [ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]\n" " [ [-s <host>] [-p <port>] [ -4 | -6 ] | [-u <socket_path>] ]\n"
" [ -a | [-t <type>] <method> [<argument>...] ]\n", stderr); " [ -a | [-t <type>] <method> [<argument>...] ]\n", stderr);
@ -916,25 +916,54 @@ static int method_to_json(char *out, size_t outlen, const char *str) {
return i; return i;
} }
static int args_to_json_length(int argc, char *argv[]) { static int args_to_json_length(int argc, char *argv[], bool encode_strings) {
int i = 0; int i = 0;
int len = 3; // "[]\0" int len = 3; // "[]\0"
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++) {
len += strlen(argv[i])+1; if (!encode_strings) {
len += strlen(argv[i])+1;
} else {
len += 3; // "\"\","
char *arg = argv[i], c;
while ((c = *arg++)) switch (c) {
case '"': len += 2; break;
case '\\': len += 2; break;
default: len++;
}
}
}
return len; return len;
} }
static int args_to_json(char *out, size_t outlen, unsigned int argc, char *argv[]) { static int args_to_json(char *out, size_t outlen, unsigned int argc, char *argv[], bool encode_strings) {
size_t i = 0; size_t i = 0;
size_t j; size_t j;
if (i+1 > outlen) return -1; if (i+1 > outlen) return -1;
out[i++] = '['; out[i++] = '[';
for (j = 0; j < argc; j++) { for (j = 0; j < argc; j++) {
size_t len = strlen(argv[j]); if (!encode_strings) {
if (j > 0) out[i++] = ','; size_t len = strlen(argv[j]);
if (i+len > outlen) return -1; if (j > 0) out[i++] = ',';
strncpy(out+i, argv[j], len); if (i+len > outlen) return -1;
i += len; strncpy(out+i, argv[j], len);
i += len;
} else {
char *arg = argv[j];
char c;
if (j > 0) {
if (i+1 > outlen) return -1;
out[i++] = ',';
}
if (i+1 > outlen) return -1;
out[i++] = '"';
while ((c = *arg++)) {
if (i+2 > outlen) return -1;
if (c == '"' || c == '\\') out[i++] = '\\';
out[i++] = c;
}
if (i+1 > outlen) return -1;
out[i++] = '"';
}
} }
if (i+2 > outlen) return -1; if (i+2 > outlen) return -1;
out[i++] = ']'; out[i++] = ']';
@ -972,6 +1001,7 @@ int main(int argc, char *argv[]) {
bool ipv4_arg = false; bool ipv4_arg = false;
bool ipv6_arg = false; bool ipv6_arg = false;
bool passthrough = false; bool passthrough = false;
bool strings = false;
enum ip_family ip_family; enum ip_family ip_family;
get_app_dir(app_dir, sizeof(app_dir)); get_app_dir(app_dir, sizeof(app_dir));
@ -1008,6 +1038,7 @@ int main(int argc, char *argv[]) {
case 'a': passthrough = true; break; case 'a': passthrough = true; break;
case 'l': no_newline = true; break; case 'l': no_newline = true; break;
case 'r': raw = true; no_newline = true; break; case 'r': raw = true; no_newline = true; break;
case 'e': strings = true; break;
default: usage(); default: usage();
} }
} }
@ -1027,7 +1058,7 @@ int main(int argc, char *argv[]) {
memcpy(shs_cap_key, ssb_cap, 32); memcpy(shs_cap_key, ssb_cap, 32);
} }
argument_len = test ? 0 : args_to_json_length(argc-i, argv+i); argument_len = test ? 0 : args_to_json_length(argc-i, argv+i, strings);
char argument[argument_len]; char argument[argument_len];
if (passthrough) { if (passthrough) {
@ -1037,7 +1068,7 @@ int main(int argc, char *argv[]) {
if (test) errx(1, "-a option conflicts with -T test"); if (test) errx(1, "-a option conflicts with -T test");
} else if (!test) { } else if (!test) {
rc = args_to_json(argument, sizeof(argument), argc-i, argv+i); rc = args_to_json(argument, sizeof(argument), argc-i, argv+i, strings);
if (rc < 0) errx(1, "unable to collect arguments"); if (rc < 0) errx(1, "unable to collect arguments");
char manifest_buf[8192]; char manifest_buf[8192];

Loading…
Cancel
Save