Skip to content

Commit

Permalink
fixes nanomsg#1007 nngcat should accept data from stdin
Browse files Browse the repository at this point in the history
Allows passing a filename of `-` to the `--file` option in order to read from
stdin. Also removes the requirement for the file to be seekable - this allows
nngcat to be used as part of a shell pipeline, or with other non-seekable files
  • Loading branch information
ehaas authored and gdamore committed May 26, 2020
1 parent 88c8eb8 commit bdbddbc
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 16 deletions.
2 changes: 1 addition & 1 deletion docs/man/nngcat.1.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ Protocols that support sending data can use these options to select the data.
Use _DATA_ for the body of outgoing messages.

*-F, --file*=_FILE_::
Use _FILE_ for the body of outgoing messages.
Use _FILE_ for the body of outgoing messages. If _FILE_ is _-_ the message body will be read from standard input.

*-i, --interval*=_SEC_::
For protocols that send unsolicited data (as opposed to those that
Expand Down
1 change: 1 addition & 0 deletions tools/nngcat/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ if (NNG_ENABLE_NNGCAT)
add_nngcat_test (nngcat_pubsub 20)
add_nngcat_test (nngcat_recvmaxsz 20)
add_nngcat_test (nngcat_unlimited 20)
add_nngcat_test (nngcat_stdin_pipe 20)
endif()
endif()
56 changes: 41 additions & 15 deletions tools/nngcat/nngcat.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//
// Copyright 2019 Staysail Systems, Inc. <[email protected]>
// Copyright 2018 Capitar IT Group BV <[email protected]>
// Copyright 2020 Lager Data, Inc. <[email protected]>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
Expand Down Expand Up @@ -272,7 +273,8 @@ help(void)
printf(" --key <file>\n");
printf(" --zt-home <path>\n");
printf("\n<src> may be one of:\n");
printf(" --file <file> (or alias -F <file>)\n");
printf(" --file <file> (or alias -F <file>). "
"Use - for standard input.\n");
printf(" --data <data> (or alias -D <data>)\n");
exit(1);
}
Expand Down Expand Up @@ -309,28 +311,52 @@ static void
loadfile(const char *path, void **datap, size_t *lenp)
{
FILE * f;
size_t total_read = 0;
size_t allocation_size = BUFSIZ;
char * fdata;
size_t len;
char * realloc_result;

if ((f = fopen(path, "r")) == NULL) {
fatal("Cannot open file %s: %s", path, strerror(errno));
}
if (fseek(f, 0, SEEK_END) != 0) {
fatal("Cannot seek to end of file: %s", strerror(errno));
if (strcmp(path, "-") == 0) {
f = stdin;
} else {
if ((f = fopen(path, "rb")) == NULL) {
fatal("Cannot open file %s: %s", path, strerror(errno));
}
}
len = ftell(f);
(void) fseek(f, 0, SEEK_SET);
if ((fdata = malloc(len + 1)) == NULL) {

if ((fdata = malloc(allocation_size + 1)) == NULL) {
fatal("Out of memory.");
}
fdata[len] = '\0';

if (fread(fdata, 1, len, f) != len) {
fatal("Read file %s failed: %s", path, strerror(errno));
while (1) {
total_read += fread(fdata + total_read, 1, allocation_size - total_read, f);
if (ferror(f)) {
if (errno == EINTR) {
continue;
}
fatal("Read from %s failed: %s", path, strerror(errno));
}
if (feof(f)) {
break;
}
if (total_read == allocation_size) {
if (allocation_size > SIZE_MAX / 2) {
fatal("Out of memory.");
}
allocation_size *= 2;
if ((realloc_result = realloc(fdata, allocation_size + 1)) == NULL) {
free(fdata);
fatal("Out of memory.");
}
fdata = realloc_result;
}
}
if (f != stdin) {
fclose(f);
}
fclose(f);
fdata[total_read] = '\0';
*datap = fdata;
*lenp = len;
*lenp = total_read;
}

static void
Expand Down
44 changes: 44 additions & 0 deletions tools/nngcat/nngcat_stdin_pipe_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

#
# Copyright 2018 Staysail Systems, Inc. <[email protected]>
# Copyright 2018 Capitar IT Group BV <[email protected]>
# Copyright 2020 Lager Data, Inc. <[email protected]>
#
# This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this
# file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT.
#

NNGCAT=${NNGCAT:=$1}
NNGCAT=${NNGCAT:-./nngcat}
ADDR="ipc:///tmp/nngcat_stdin_pipe_test"
OUTPUT=/tmp/nngcat_stdin_pipe_test.$$.out

echo -n "Verify reading from stdin pipe: "

trap "rm $OUTPUT" 0

${NNGCAT} --listen ${ADDR} --count=1 --recv-timeout=3 --recv-maxsz=0 --pull0 --raw > $OUTPUT 2>/dev/null &
bgid=$!

sleep 1
# for speed of execution, run these in the background, they should be ignored
echo "hello world" | ${NNGCAT} --connect ${ADDR} --delay=1 --push0 --file -
wait "$bgid" 2>/dev/null

sum=$(cksum ${OUTPUT})
sum=${sum%% *}

# This matches "hello world\n" since echo adds a trailing newline
if [[ ${sum} == 3733384285 ]]
then
echo "pass"
exit 0
fi
echo "FAIL: Checksum failed (Wanted 3733384285 got ${sum})"
echo "OUTPUT:"
ls -la ${OUTPUT}

exit 1

0 comments on commit bdbddbc

Please sign in to comment.