From f3842b94c22c771a201eea4d99d79f2a414f5c2e Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Wed, 16 Dec 2015 15:17:57 +0100 Subject: support input from terminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/send.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 109 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/send.c b/src/send.c index 20ddea6..2094fee 100644 --- a/src/send.c +++ b/src/send.c @@ -21,6 +21,9 @@ #include #include /* dep: alsa-lib (pkg-config alsa) */ #include +#include +#include +#include @@ -209,6 +212,102 @@ static int send_byte_with_ecc(int c) } +/** + * Transmit a chunk of bytes. + * + * @param buf The chunk to transmit. + * @param n The number of bytes in the chunk. + * @return 0 on success, -1 on failure. + */ +static int send_chunk(char* buf, size_t n) +{ + size_t i; + int c; + + for (i = 0; i < n; i++) + { + c = buf[i]; + if ((c == CHAR_ESCAPE) || (c == CHAR_CANCEL) || (c == CHAR_END)) + if (send_byte_with_ecc(CHAR_ESCAPE)) + goto qfile; + if (send_byte_with_ecc(c)) + goto qfile; + } + + return 0; + qfile: + errno = 0; + fail: + return -1; +} + + +/** + * Read all input from stdin and transmit it as it is being read. + * + * @return 0 on success, -1 on failure. + */ +static int send_file(void) +{ + char buf[1024]; + ssize_t n; + + for (;;) + { + n = read(STDIN_FILENO, buf, sizeof(buf)); + if (n < 0) goto fail; + if (n == 0) break; + if (send_chunk(buf, (size_t)n)) + goto fail; + } + + return 0; + fail: + return -1; +} + + +/** + * Read all input from stdin, and then transmit it. + * + * @return 0 on success, -1 on failure. + */ +static int send_term(void) +{ + char* buf = NULL; + size_t size = 0; + size_t ptr = 0; + ssize_t n; + void* new; + int saved_errno; + + for (;;) + { + if (ptr == size) + { + size = size ? (size << 1) : 128; + new = realloc(buf, size); + if (new == NULL) + goto fail; + buf = new; + } + n = read(STDIN_FILENO, buf + ptr, size - ptr); + if (n < 0) goto fail; + if (n == 0) break; + ptr += (size_t)n; + } + if (send_chunk(buf, ptr)) + goto fail; + + return 0; + fail: + saved_errno = errno; + free(buf); + errno = saved_errno; + return -1; +} + + /** * Transmit a file over audio. * @@ -219,9 +318,7 @@ static int send_byte_with_ecc(int c) int main(int argc, char* argv[]) { struct sigaction act; - char buf[1024]; - int r, c, rc = 1; - ssize_t n, i; + int r, rc = 1; argv0 = argc ? argv[0] : ""; @@ -251,23 +348,16 @@ int main(int argc, char* argv[]) if (r < 0) return fprintf(stderr, "%s: snd_pcm_set_params: %s\n", *argv, snd_strerror(r)), 1; - /* TODO: if reading from the terminal, wait until all input is fetched. */ /* Send message. */ - for (;;) + if (isatty(STDIN_FILENO)) { - n = read(STDIN_FILENO, buf, sizeof(buf)); - if (n < 0) goto fail; - if (n == 0) break; - for (i = 0; i < n; i++) - { - c = buf[i]; - if ((c == CHAR_ESCAPE) || (c == CHAR_CANCEL) || (c == CHAR_END)) - if (send_byte_with_ecc(CHAR_ESCAPE)) - goto cleanup; - if (send_byte_with_ecc(c)) - goto cleanup; - } + if (send_term()) + goto fail; } + else + if (send_file()) + goto fail; + /* Mark end of transmission. */ if (send_byte_with_ecc(CHAR_END)) goto cleanup; if (send_byte_with_ecc(-CHAR_END)) goto cleanup; @@ -276,7 +366,8 @@ int main(int argc, char* argv[]) rc = 0; goto cleanup; fail: - perror(argv0); + if (errno) + perror(argv0); cleanup: snd_pcm_close(sound_handle); /* Mark aborted transmission. */ -- cgit v1.2.3-70-g09d2